Skip to content

Commit

Permalink
free client's multi state when it becomes dirty (#961)
Browse files Browse the repository at this point in the history
Release the client's MULTI state when the transaction becomes dirty to
save memory.

---------

Signed-off-by: zhaozhao.zz <zhaozhao.zz@alibaba-inc.com>
  • Loading branch information
soloestoy authored and madolson committed Sep 2, 2024
1 parent a02c532 commit ea485b0
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/multi.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ void freeClientMultiState(client *c) {
zfree(c->mstate.commands);
}

void resetClientMultiState(client *c) {
if (c->mstate.commands) {
freeClientMultiState(c);
initClientMultiState(c);
}
}

/* Add a new command into the MULTI commands queue */
void queueMultiCommand(client *c, uint64_t cmd_flags) {
multiCmd *mc;
Expand Down Expand Up @@ -94,8 +101,7 @@ void queueMultiCommand(client *c, uint64_t cmd_flags) {
}

void discardTransaction(client *c) {
freeClientMultiState(c);
initClientMultiState(c);
resetClientMultiState(c);
c->flag.multi = 0;
c->flag.dirty_cas = 0;
c->flag.dirty_exec = 0;
Expand All @@ -105,7 +111,10 @@ void discardTransaction(client *c) {
/* Flag the transaction as DIRTY_EXEC so that EXEC will fail.
* Should be called every time there is an error while queueing a command. */
void flagTransaction(client *c) {
if (c->flag.multi) c->flag.dirty_exec = 1;
if (c->flag.multi) {
c->flag.dirty_exec = 1;
resetClientMultiState(c);
}
}

void multiCommand(client *c) {
Expand Down Expand Up @@ -391,6 +400,7 @@ void touchWatchedKey(serverDb *db, robj *key) {
}

c->flag.dirty_cas = 1;
resetClientMultiState(c);
/* As the client is marked as dirty, there is no point in getting here
* again in case that key (or others) are modified again (or keep the
* memory overhead till EXEC). */
Expand Down Expand Up @@ -442,6 +452,7 @@ void touchAllWatchedKeysInDb(serverDb *emptied, serverDb *replaced_with) {
}
client *c = wk->client;
c->flag.dirty_cas = 1;
resetClientMultiState(c);
/* Note - we could potentially call unwatchAllKeys for this specific client in order to reduce
* the total number of iterations. BUT this could also free the current next entry pointer
* held by the iterator and can lead to use-after-free. */
Expand Down

0 comments on commit ea485b0

Please sign in to comment.