Propagate GETSET and SET-GET as SET (#7957)

- Generates a more backwards compatible command stream
- Slightly more efficient execution in replica/AOF
- Add a test for coverage
This commit is contained in:
Oran Agra 2020-11-03 14:56:57 +02:00 committed by GitHub
parent 1a91a2700b
commit 9122379abc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 1 deletions

View File

@ -90,7 +90,7 @@ void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire,
}
if (flags & OBJ_SET_GET) {
getGenericCommand(c);
getGenericCommand(c);
}
genericSetKey(c,c->db,key,val,flags & OBJ_SET_KEEPTTL,1);
@ -160,6 +160,24 @@ void setCommand(client *c) {
c->argv[2] = tryObjectEncoding(c->argv[2]);
setGenericCommand(c,flags,c->argv[1],c->argv[2],expire,unit,NULL,NULL);
/* Propagate without the GET argument */
if (flags & OBJ_SET_GET) {
int argc = 0;
robj **argv = zmalloc((c->argc-1)*sizeof(robj*));
for (j=0; j < c->argc; j++) {
char *a = c->argv[j]->ptr;
/* Skip GET which may be repeated multiple times. */
if (j >= 3 &&
(a[0] == 'g' || a[0] == 'G') &&
(a[1] == 'e' || a[1] == 'E') &&
(a[2] == 't' || a[2] == 'T') && a[3] == '\0')
continue;
argv[argc++] = c->argv[j];
incrRefCount(c->argv[j]);
}
replaceClientCommandVector(c, argc, argv);
}
}
void setnxCommand(client *c) {
@ -201,6 +219,11 @@ void getsetCommand(client *c) {
setKey(c,c->db,c->argv[1],c->argv[2]);
notifyKeyspaceEvent(NOTIFY_STRING,"set",c->argv[1],c->db->id);
server.dirty++;
/* Propagate as SET command */
robj *setcmd = createStringObject("SET",3);
rewriteClientCommandArgument(c,0,setcmd);
decrRefCount(setcmd);
}
void setrangeCommand(client *c) {

View File

@ -77,6 +77,27 @@ start_server {tags {"repl"}} {
assert_equal [$A debug digest] [$B debug digest]
}
test {GETSET replication} {
$A config resetstat
$A config set loglevel debug
$B config set loglevel debug
r set test foo
assert_equal [r getset test bar] foo
wait_for_condition 500 10 {
[$A get test] eq "bar"
} else {
fail "getset wasn't propagated"
}
assert_equal [r set test vaz get] bar
wait_for_condition 500 10 {
[$A get test] eq "vaz"
} else {
fail "set get wasn't propagated"
}
assert_match {*calls=3,*} [cmdrstat set $A]
assert_match {} [cmdrstat getset $A]
}
test {BRPOPLPUSH replication, when blocking against empty list} {
$A config resetstat
set rd [redis_deferring_client]