free client's multi state when it becomes dirty (#961)
Release the client's MULTI state when the transaction becomes dirty to save memory. --------- Signed-off-by: zhaozhao.zz <zhaozhao.zz@alibaba-inc.com>
This commit is contained in:
parent
ad0ede302c
commit
4a9b4f667c
17
src/multi.c
17
src/multi.c
@ -55,6 +55,13 @@ void freeClientMultiState(client *c) {
|
|||||||
zfree(c->mstate.commands);
|
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 */
|
/* Add a new command into the MULTI commands queue */
|
||||||
void queueMultiCommand(client *c, uint64_t cmd_flags) {
|
void queueMultiCommand(client *c, uint64_t cmd_flags) {
|
||||||
multiCmd *mc;
|
multiCmd *mc;
|
||||||
@ -94,8 +101,7 @@ void queueMultiCommand(client *c, uint64_t cmd_flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void discardTransaction(client *c) {
|
void discardTransaction(client *c) {
|
||||||
freeClientMultiState(c);
|
resetClientMultiState(c);
|
||||||
initClientMultiState(c);
|
|
||||||
c->flag.multi = 0;
|
c->flag.multi = 0;
|
||||||
c->flag.dirty_cas = 0;
|
c->flag.dirty_cas = 0;
|
||||||
c->flag.dirty_exec = 0;
|
c->flag.dirty_exec = 0;
|
||||||
@ -105,7 +111,10 @@ void discardTransaction(client *c) {
|
|||||||
/* Flag the transaction as DIRTY_EXEC so that EXEC will fail.
|
/* Flag the transaction as DIRTY_EXEC so that EXEC will fail.
|
||||||
* Should be called every time there is an error while queueing a command. */
|
* Should be called every time there is an error while queueing a command. */
|
||||||
void flagTransaction(client *c) {
|
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) {
|
void multiCommand(client *c) {
|
||||||
@ -391,6 +400,7 @@ void touchWatchedKey(serverDb *db, robj *key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c->flag.dirty_cas = 1;
|
c->flag.dirty_cas = 1;
|
||||||
|
resetClientMultiState(c);
|
||||||
/* As the client is marked as dirty, there is no point in getting here
|
/* 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
|
* again in case that key (or others) are modified again (or keep the
|
||||||
* memory overhead till EXEC). */
|
* memory overhead till EXEC). */
|
||||||
@ -442,6 +452,7 @@ void touchAllWatchedKeysInDb(serverDb *emptied, serverDb *replaced_with) {
|
|||||||
}
|
}
|
||||||
client *c = wk->client;
|
client *c = wk->client;
|
||||||
c->flag.dirty_cas = 1;
|
c->flag.dirty_cas = 1;
|
||||||
|
resetClientMultiState(c);
|
||||||
/* Note - we could potentially call unwatchAllKeys for this specific client in order to reduce
|
/* 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
|
* 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. */
|
* held by the iterator and can lead to use-after-free. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user