/* Forward declaration */ staticintgetExpireMillisecondsOrReply(client *c, robj *expire, int flags, int unit, longlong *milliseconds);
voidsetGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire, int unit, robj *ok_reply, robj *abort_reply){ longlong milliseconds = 0; /* initialized to avoid any harmness warning */ int found = 0; int setkey_flags = 0;
if (expire && getExpireMillisecondsOrReply(c, expire, flags, unit, &milliseconds) != C_OK) { return; }
if (flags & OBJ_SET_GET) { if (getGenericCommand(c) == C_ERR) return; }
/* When expire is not NULL, we avoid deleting the TTL so it can be updated later instead of being deleted and then created again. */ setkey_flags |= ((flags & OBJ_KEEPTTL) || expire) ? SETKEY_KEEPTTL : 0; setkey_flags |= found ? SETKEY_ALREADY_EXIST : SETKEY_DOESNT_EXIST;
if (expire) { setExpire(c,c->db,key,milliseconds); /* Propagate as SET Key Value PXAT millisecond-timestamp if there is * EX/PX/EXAT flag. */ if (!(flags & OBJ_PXAT)) { robj *milliseconds_obj = createStringObjectFromLongLong(milliseconds); rewriteClientCommandVector(c, 5, shared.set, key, val, shared.pxat, milliseconds_obj); decrRefCount(milliseconds_obj); } notifyKeyspaceEvent(NOTIFY_GENERIC,"expire",key,c->db->id); }
/* Propagate without the GET argument (Isn't needed if we had expire since in that case we completely re-written the command argv) */ if ((flags & OBJ_SET_GET) && !expire) { int argc = 0; int j; 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); } }