"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/t_string.c" between
redis-6.2-rc3.tar.gz and redis-6.2.0.tar.gz

About: redis is an advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets.

t_string.c  (redis-6.2-rc3):t_string.c  (redis-6.2.0)
skipping to change at line 76 skipping to change at line 76
#define OBJ_SET_XX (1<<1) /* Set if key exists. */ #define OBJ_SET_XX (1<<1) /* Set if key exists. */
#define OBJ_EX (1<<2) /* Set if time in seconds is given */ #define OBJ_EX (1<<2) /* Set if time in seconds is given */
#define OBJ_PX (1<<3) /* Set if time in ms in given */ #define OBJ_PX (1<<3) /* Set if time in ms in given */
#define OBJ_KEEPTTL (1<<4) /* Set and keep the ttl */ #define OBJ_KEEPTTL (1<<4) /* Set and keep the ttl */
#define OBJ_SET_GET (1<<5) /* Set if want to get key before set */ #define OBJ_SET_GET (1<<5) /* Set if want to get key before set */
#define OBJ_EXAT (1<<6) /* Set if timestamp in second is given */ #define OBJ_EXAT (1<<6) /* Set if timestamp in second is given */
#define OBJ_PXAT (1<<7) /* Set if timestamp in ms is given */ #define OBJ_PXAT (1<<7) /* Set if timestamp in ms is given */
#define OBJ_PERSIST (1<<8) /* Set if we need to remove the ttl */ #define OBJ_PERSIST (1<<8) /* Set if we need to remove the ttl */
void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire, int unit, robj *ok_reply, robj *abort_reply) { void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire, int unit, robj *ok_reply, robj *abort_reply) {
long long milliseconds = 0; /* initialized to avoid any harmness warning */ long long milliseconds = 0, when = 0; /* initialized to avoid any harmness w arning */
if (expire) { if (expire) {
if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != C_OK ) if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != C_OK )
return; return;
if (milliseconds <= 0) { if (milliseconds <= 0 || (unit == UNIT_SECONDS && milliseconds > LLONG_M
addReplyErrorFormat(c,"invalid expire time in %s",c->cmd->name); AX / 1000)) {
/* Negative value provided or multiplication is gonna overflow. */
addReplyErrorFormat(c, "invalid expire time in %s", c->cmd->name);
return; return;
} }
if (unit == UNIT_SECONDS) milliseconds *= 1000; if (unit == UNIT_SECONDS) milliseconds *= 1000;
when = milliseconds;
if ((flags & OBJ_PX) || (flags & OBJ_EX))
when += mstime();
if (when <= 0) {
/* Overflow detected. */
addReplyErrorFormat(c, "invalid expire time in %s", c->cmd->name);
return;
}
} }
if ((flags & OBJ_SET_NX && lookupKeyWrite(c->db,key) != NULL) || if ((flags & OBJ_SET_NX && lookupKeyWrite(c->db,key) != NULL) ||
(flags & OBJ_SET_XX && lookupKeyWrite(c->db,key) == NULL)) (flags & OBJ_SET_XX && lookupKeyWrite(c->db,key) == NULL))
{ {
addReply(c, abort_reply ? abort_reply : shared.null[c->resp]); addReply(c, abort_reply ? abort_reply : shared.null[c->resp]);
return; return;
} }
if (flags & OBJ_SET_GET) { if (flags & OBJ_SET_GET) {
if (getGenericCommand(c) == C_ERR) return; if (getGenericCommand(c) == C_ERR) return;
} }
genericSetKey(c,c->db,key, val,flags & OBJ_KEEPTTL,1); genericSetKey(c,c->db,key, val,flags & OBJ_KEEPTTL,1);
server.dirty++; server.dirty++;
notifyKeyspaceEvent(NOTIFY_STRING,"set",key,c->db->id); notifyKeyspaceEvent(NOTIFY_STRING,"set",key,c->db->id);
if (expire) { if (expire) {
robj *exp = shared.pxat; setExpire(c,c->db,key,when);
if ((flags & OBJ_PX) || (flags & OBJ_EX)) {
setExpire(c,c->db,key,milliseconds + mstime());
exp = shared.px;
} else {
setExpire(c,c->db,key,milliseconds);
}
notifyKeyspaceEvent(NOTIFY_GENERIC,"expire",key,c->db->id); notifyKeyspaceEvent(NOTIFY_GENERIC,"expire",key,c->db->id);
/* Propagate as SET Key Value PXAT millisecond-timestamp if there is EXA T/PXAT or /* Propagate as SET Key Value PXAT millisecond-timestamp if there is EXA T/PXAT or
* propagate as SET Key Value PX millisecond if there is EX/PX flag. * propagate as SET Key Value PX millisecond if there is EX/PX flag.
* *
* Additionally when we propagate the SET with PX (relative millisecond) we translate * Additionally when we propagate the SET with PX (relative millisecond) we translate
* it again to SET with PXAT for the AOF. * it again to SET with PXAT for the AOF.
* *
* Additional care is required while modifying the argument order. AOF r elies on the * Additional care is required while modifying the argument order. AOF r elies on the
* exp argument being at index 3. (see feedAppendOnlyFile) * exp argument being at index 3. (see feedAppendOnlyFile)
* */ * */
robj *exp = (flags & OBJ_PXAT) || (flags & OBJ_EXAT) ? shared.pxat : sha red.px;
robj *millisecondObj = createStringObjectFromLongLong(milliseconds); robj *millisecondObj = createStringObjectFromLongLong(milliseconds);
rewriteClientCommandVector(c,5,shared.set,key,val,exp,millisecondObj); rewriteClientCommandVector(c,5,shared.set,key,val,exp,millisecondObj);
decrRefCount(millisecondObj); decrRefCount(millisecondObj);
} }
if (!(flags & OBJ_SET_GET)) { if (!(flags & OBJ_SET_GET)) {
addReply(c, ok_reply ? ok_reply : shared.ok); addReply(c, ok_reply ? ok_reply : shared.ok);
} }
/* Propagate without the GET argument (Isn't needed if we had expire since i n that case we completely re-written the command argv) */ /* Propagate without the GET argument (Isn't needed if we had expire since i n that case we completely re-written the command argv) */
if ((flags & OBJ_SET_GET) && !expire) { if ((flags & OBJ_SET_GET) && !expire) {
skipping to change at line 338 skipping to change at line 341
robj *o; robj *o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == NULL) if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.null[c->resp])) == NULL)
return; return;
if (checkType(c,o,OBJ_STRING)) { if (checkType(c,o,OBJ_STRING)) {
return; return;
} }
long long milliseconds = 0; long long milliseconds = 0, when = 0;
/* Validate the expiration time value first */ /* Validate the expiration time value first */
if (expire) { if (expire) {
if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != C_OK ) if (getLongLongFromObjectOrReply(c, expire, &milliseconds, NULL) != C_OK )
return; return;
if (milliseconds <= 0) { if (milliseconds <= 0 || (unit == UNIT_SECONDS && milliseconds > LLONG_M
addReplyErrorFormat(c,"invalid expire time in %s",c->cmd->name); AX / 1000)) {
/* Negative value provided or multiplication is gonna overflow. */
addReplyErrorFormat(c, "invalid expire time in %s", c->cmd->name);
return; return;
} }
if (unit == UNIT_SECONDS) milliseconds *= 1000; if (unit == UNIT_SECONDS) milliseconds *= 1000;
when = milliseconds;
if ((flags & OBJ_PX) || (flags & OBJ_EX))
when += mstime();
if (when <= 0) {
/* Overflow detected. */
addReplyErrorFormat(c, "invalid expire time in %s", c->cmd->name);
return;
}
} }
/* We need to do this before we expire the key or delete it */ /* We need to do this before we expire the key or delete it */
addReplyBulk(c,o); addReplyBulk(c,o);
/* This command is never propagated as is. It is either propagated as PEXPIR E[AT],DEL,UNLINK or PERSIST. /* This command is never propagated as is. It is either propagated as PEXPIR E[AT],DEL,UNLINK or PERSIST.
* This why it doesn't need special handling in feedAppendOnlyFile to conver t relative expire time to absolute one. */ * This why it doesn't need special handling in feedAppendOnlyFile to conver t relative expire time to absolute one. */
if (((flags & OBJ_PXAT) || (flags & OBJ_EXAT)) && checkAlreadyExpired(millis econds)) { if (((flags & OBJ_PXAT) || (flags & OBJ_EXAT)) && checkAlreadyExpired(millis econds)) {
/* When PXAT/EXAT absolute timestamp is specified, there can be a chance that timestamp /* When PXAT/EXAT absolute timestamp is specified, there can be a chance that timestamp
* has already elapsed so delete the key in that case. */ * has already elapsed so delete the key in that case. */
int deleted = server.lazyfree_lazy_expire ? dbAsyncDelete(c->db, c->argv [1]) : int deleted = server.lazyfree_lazy_expire ? dbAsyncDelete(c->db, c->argv [1]) :
dbSyncDelete(c->db, c->argv[1]); dbSyncDelete(c->db, c->argv[1]);
serverAssert(deleted); serverAssert(deleted);
robj *aux = server.lazyfree_lazy_expire ? shared.unlink : shared.del; robj *aux = server.lazyfree_lazy_expire ? shared.unlink : shared.del;
rewriteClientCommandVector(c,2,aux,c->argv[1]); rewriteClientCommandVector(c,2,aux,c->argv[1]);
signalModifiedKey(c, c->db, c->argv[1]); signalModifiedKey(c, c->db, c->argv[1]);
notifyKeyspaceEvent(NOTIFY_GENERIC, "del", c->argv[1], c->db->id); notifyKeyspaceEvent(NOTIFY_GENERIC, "del", c->argv[1], c->db->id);
server.dirty++; server.dirty++;
} else if (expire) { } else if (expire) {
robj *exp = shared.pexpireat; setExpire(c,c->db,c->argv[1],when);
if ((flags & OBJ_PX) || (flags & OBJ_EX)) { /* Propagate */
setExpire(c,c->db,c->argv[1],milliseconds + mstime()); robj *exp = (flags & OBJ_PXAT) || (flags & OBJ_EXAT) ? shared.pexpireat
exp = shared.pexpire; : shared.pexpire;
} else {
setExpire(c,c->db,c->argv[1],milliseconds);
}
robj* millisecondObj = createStringObjectFromLongLong(milliseconds); robj* millisecondObj = createStringObjectFromLongLong(milliseconds);
rewriteClientCommandVector(c,3,exp,c->argv[1],millisecondObj); rewriteClientCommandVector(c,3,exp,c->argv[1],millisecondObj);
decrRefCount(millisecondObj); decrRefCount(millisecondObj);
signalModifiedKey(c, c->db, c->argv[1]); signalModifiedKey(c, c->db, c->argv[1]);
notifyKeyspaceEvent(NOTIFY_GENERIC,"expire",c->argv[1],c->db->id); notifyKeyspaceEvent(NOTIFY_GENERIC,"expire",c->argv[1],c->db->id);
server.dirty++; server.dirty++;
} else if (flags & OBJ_PERSIST) { } else if (flags & OBJ_PERSIST) {
if (removeExpire(c->db, c->argv[1])) { if (removeExpire(c->db, c->argv[1])) {
signalModifiedKey(c, c->db, c->argv[1]); signalModifiedKey(c, c->db, c->argv[1]);
rewriteClientCommandVector(c, 2, shared.persist, c->argv[1]); rewriteClientCommandVector(c, 2, shared.persist, c->argv[1]);
skipping to change at line 634 skipping to change at line 641
void decrbyCommand(client *c) { void decrbyCommand(client *c) {
long long incr; long long incr;
if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != C_OK) return ; if (getLongLongFromObjectOrReply(c, c->argv[2], &incr, NULL) != C_OK) return ;
incrDecrCommand(c,-incr); incrDecrCommand(c,-incr);
} }
void incrbyfloatCommand(client *c) { void incrbyfloatCommand(client *c) {
long double incr, value; long double incr, value;
robj *o, *new, *aux; robj *o, *new;
o = lookupKeyWrite(c->db,c->argv[1]); o = lookupKeyWrite(c->db,c->argv[1]);
if (checkType(c,o,OBJ_STRING)) return; if (checkType(c,o,OBJ_STRING)) return;
if (getLongDoubleFromObjectOrReply(c,o,&value,NULL) != C_OK || if (getLongDoubleFromObjectOrReply(c,o,&value,NULL) != C_OK ||
getLongDoubleFromObjectOrReply(c,c->argv[2],&incr,NULL) != C_OK) getLongDoubleFromObjectOrReply(c,c->argv[2],&incr,NULL) != C_OK)
return; return;
value += incr; value += incr;
if (isnan(value) || isinf(value)) { if (isnan(value) || isinf(value)) {
addReplyError(c,"increment would produce NaN or Infinity"); addReplyError(c,"increment would produce NaN or Infinity");
skipping to change at line 662 skipping to change at line 669
signalModifiedKey(c,c->db,c->argv[1]); signalModifiedKey(c,c->db,c->argv[1]);
notifyKeyspaceEvent(NOTIFY_STRING,"incrbyfloat",c->argv[1],c->db->id); notifyKeyspaceEvent(NOTIFY_STRING,"incrbyfloat",c->argv[1],c->db->id);
server.dirty++; server.dirty++;
addReplyBulk(c,new); addReplyBulk(c,new);
/* Always replicate INCRBYFLOAT as a SET command with the final value /* Always replicate INCRBYFLOAT as a SET command with the final value
* in order to make sure that differences in float precision or formatting * in order to make sure that differences in float precision or formatting
* will not create differences in replicas or after an AOF restart. */ * will not create differences in replicas or after an AOF restart. */
rewriteClientCommandArgument(c,0,shared.set); rewriteClientCommandArgument(c,0,shared.set);
rewriteClientCommandArgument(c,2,new); rewriteClientCommandArgument(c,2,new);
aux = createStringObject("KEEPTTL",7); rewriteClientCommandArgument(c,3,shared.keepttl);
rewriteClientCommandArgument(c,3,aux);
decrRefCount(aux);
} }
void appendCommand(client *c) { void appendCommand(client *c) {
size_t totlen; size_t totlen;
robj *o, *append; robj *o, *append;
o = lookupKeyWrite(c->db,c->argv[1]); o = lookupKeyWrite(c->db,c->argv[1]);
if (o == NULL) { if (o == NULL) {
/* Create the key */ /* Create the key */
c->argv[2] = tryObjectEncoding(c->argv[2]); c->argv[2] = tryObjectEncoding(c->argv[2]);
skipping to change at line 766 skipping to change at line 771
goto cleanup; goto cleanup;
} }
obja = lookupKeyRead(c->db,c->argv[j+1]); obja = lookupKeyRead(c->db,c->argv[j+1]);
objb = lookupKeyRead(c->db,c->argv[j+2]); objb = lookupKeyRead(c->db,c->argv[j+2]);
if ((obja && obja->type != OBJ_STRING) || if ((obja && obja->type != OBJ_STRING) ||
(objb && objb->type != OBJ_STRING)) (objb && objb->type != OBJ_STRING))
{ {
addReplyError(c, addReplyError(c,
"The specified keys must contain string values"); "The specified keys must contain string values");
/* Don't cleanup the objects, we need to do that /* Don't cleanup the objects, we need to do that
* only after callign getDecodedObject(). */ * only after calling getDecodedObject(). */
obja = NULL; obja = NULL;
objb = NULL; objb = NULL;
goto cleanup; goto cleanup;
} }
obja = obja ? getDecodedObject(obja) : createStringObject("",0); obja = obja ? getDecodedObject(obja) : createStringObject("",0);
objb = objb ? getDecodedObject(objb) : createStringObject("",0); objb = objb ? getDecodedObject(objb) : createStringObject("",0);
a = obja->ptr; a = obja->ptr;
b = objb->ptr; b = objb->ptr;
j += 2; j += 2;
} else { } else {
 End of changes. 12 change blocks. 
27 lines changed or deleted 35 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)