"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/t_set.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_set.c  (redis-6.2-rc3):t_set.c  (redis-6.2.0)
skipping to change at line 502 skipping to change at line 502
/* Propagate this command as a DEL operation */ /* Propagate this command as a DEL operation */
rewriteClientCommandVector(c,2,shared.del,c->argv[1]); rewriteClientCommandVector(c,2,shared.del,c->argv[1]);
signalModifiedKey(c,c->db,c->argv[1]); signalModifiedKey(c,c->db,c->argv[1]);
return; return;
} }
/* Case 2 and 3 require to replicate SPOP as a set of SREM commands. /* Case 2 and 3 require to replicate SPOP as a set of SREM commands.
* Prepare our replication argument vector. Also send the array length * Prepare our replication argument vector. Also send the array length
* which is common to both the code paths. */ * which is common to both the code paths. */
robj *propargv[3]; robj *propargv[3];
propargv[0] = createStringObject("SREM",4); propargv[0] = shared.srem;
propargv[1] = c->argv[1]; propargv[1] = c->argv[1];
addReplySetLen(c,count); addReplySetLen(c,count);
/* Common iteration vars. */ /* Common iteration vars. */
sds sdsele; sds sdsele;
robj *objele; robj *objele;
int encoding; int encoding;
int64_t llele; int64_t llele;
unsigned long remaining = size-count; /* Elements left after SPOP. */ unsigned long remaining = size-count; /* Elements left after SPOP. */
skipping to change at line 593 skipping to change at line 593
setTypeReleaseIterator(si); setTypeReleaseIterator(si);
/* Assign the new set as the key value. */ /* Assign the new set as the key value. */
dbOverwrite(c->db,c->argv[1],newset); dbOverwrite(c->db,c->argv[1],newset);
} }
/* Don't propagate the command itself even if we incremented the /* Don't propagate the command itself even if we incremented the
* dirty counter. We don't want to propagate an SPOP command since * dirty counter. We don't want to propagate an SPOP command since
* we propagated the command as a set of SREMs operations using * we propagated the command as a set of SREMs operations using
* the alsoPropagate() API. */ * the alsoPropagate() API. */
decrRefCount(propargv[0]);
preventCommandPropagation(c); preventCommandPropagation(c);
signalModifiedKey(c,c->db,c->argv[1]); signalModifiedKey(c,c->db,c->argv[1]);
} }
void spopCommand(client *c) { void spopCommand(client *c) {
robj *set, *ele, *aux; robj *set, *ele;
sds sdsele; sds sdsele;
int64_t llele; int64_t llele;
int encoding; int encoding;
if (c->argc == 3) { if (c->argc == 3) {
spopWithCountCommand(c); spopWithCountCommand(c);
return; return;
} else if (c->argc > 3) { } else if (c->argc > 3) {
addReplyErrorObject(c,shared.syntaxerr); addReplyErrorObject(c,shared.syntaxerr);
return; return;
skipping to change at line 632 skipping to change at line 631
ele = createStringObjectFromLongLong(llele); ele = createStringObjectFromLongLong(llele);
set->ptr = intsetRemove(set->ptr,llele,NULL); set->ptr = intsetRemove(set->ptr,llele,NULL);
} else { } else {
ele = createStringObject(sdsele,sdslen(sdsele)); ele = createStringObject(sdsele,sdslen(sdsele));
setTypeRemove(set,ele->ptr); setTypeRemove(set,ele->ptr);
} }
notifyKeyspaceEvent(NOTIFY_SET,"spop",c->argv[1],c->db->id); notifyKeyspaceEvent(NOTIFY_SET,"spop",c->argv[1],c->db->id);
/* Replicate/AOF this command as an SREM operation */ /* Replicate/AOF this command as an SREM operation */
aux = createStringObject("SREM",4); rewriteClientCommandVector(c,3,shared.srem,c->argv[1],ele);
rewriteClientCommandVector(c,3,aux,c->argv[1],ele);
decrRefCount(aux);
/* Add the element to the reply */ /* Add the element to the reply */
addReplyBulk(c,ele); addReplyBulk(c,ele);
decrRefCount(ele); decrRefCount(ele);
/* Delete the set if it's empty */ /* Delete the set if it's empty */
if (setTypeSize(set) == 0) { if (setTypeSize(set) == 0) {
dbDelete(c->db,c->argv[1]); dbDelete(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);
} }
skipping to change at line 680 skipping to change at line 677
if (getLongFromObjectOrReply(c,c->argv[2],&l,NULL) != C_OK) return; if (getLongFromObjectOrReply(c,c->argv[2],&l,NULL) != C_OK) return;
if (l >= 0) { if (l >= 0) {
count = (unsigned long) l; count = (unsigned long) l;
} else { } else {
/* A negative count means: return the same elements multiple times /* A negative count means: return the same elements multiple times
* (i.e. don't remove the extracted element after every extraction). */ * (i.e. don't remove the extracted element after every extraction). */
count = -l; count = -l;
uniq = 0; uniq = 0;
} }
if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptyset[c->resp])) if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptyarray))
== NULL || checkType(c,set,OBJ_SET)) return; == NULL || checkType(c,set,OBJ_SET)) return;
size = setTypeSize(set); size = setTypeSize(set);
/* If count is zero, serve it ASAP to avoid special cases later. */ /* If count is zero, serve it ASAP to avoid special cases later. */
if (count == 0) { if (count == 0) {
addReply(c,shared.emptyset[c->resp]); addReply(c,shared.emptyarray);
return; return;
} }
/* CASE 1: The count was negative, so the extraction method is just: /* CASE 1: The count was negative, so the extraction method is just:
* "return N random elements" sampling the whole set every time. * "return N random elements" sampling the whole set every time.
* This case is trivial and can be served without auxiliary data * This case is trivial and can be served without auxiliary data
* structures. This case is the only one that also needs to return the * structures. This case is the only one that also needs to return the
* elements in random order. */ * elements in random order. */
if (!uniq || count == 1) { if (!uniq || count == 1) {
addReplySetLen(c,count); addReplyArrayLen(c,count);
while(count--) { while(count--) {
encoding = setTypeRandomElement(set,&ele,&llele); encoding = setTypeRandomElement(set,&ele,&llele);
if (encoding == OBJ_ENCODING_INTSET) { if (encoding == OBJ_ENCODING_INTSET) {
addReplyBulkLongLong(c,llele); addReplyBulkLongLong(c,llele);
} else { } else {
addReplyBulkCBuffer(c,ele,sdslen(ele)); addReplyBulkCBuffer(c,ele,sdslen(ele));
} }
} }
return; return;
} }
/* CASE 2: /* CASE 2:
* The number of requested elements is greater than the number of * The number of requested elements is greater than the number of
* elements inside the set: simply return the whole set. */ * elements inside the set: simply return the whole set. */
if (count >= size) { if (count >= size) {
sunionDiffGenericCommand(c,c->argv+1,1,NULL,SET_OP_UNION); setTypeIterator *si;
addReplyArrayLen(c,size);
si = setTypeInitIterator(set);
while ((encoding = setTypeNext(si,&ele,&llele)) != -1) {
if (encoding == OBJ_ENCODING_INTSET) {
addReplyBulkLongLong(c,llele);
} else {
addReplyBulkCBuffer(c,ele,sdslen(ele));
}
size--;
}
setTypeReleaseIterator(si);
serverAssert(size==0);
return; return;
} }
/* For CASE 3 and CASE 4 we need an auxiliary dictionary. */ /* For CASE 3 and CASE 4 we need an auxiliary dictionary. */
d = dictCreate(&sdsReplyDictType,NULL); d = dictCreate(&sdsReplyDictType,NULL);
/* CASE 3: /* CASE 3:
* The number of elements inside the set is not greater than * The number of elements inside the set is not greater than
* SRANDMEMBER_SUB_STRATEGY_MUL times the number of requested elements. * SRANDMEMBER_SUB_STRATEGY_MUL times the number of requested elements.
* In this case we create a set from scratch with all the elements, and * In this case we create a set from scratch with all the elements, and
* subtract random elements to reach the requested number of elements. * subtract random elements to reach the requested number of elements.
* *
* This is done because if the number of requested elements is just * This is done because if the number of requested elements is just
* a bit less than the number of elements in the set, the natural approach * a bit less than the number of elements in the set, the natural approach
* used into CASE 4 is highly inefficient. */ * used into CASE 4 is highly inefficient. */
if (count*SRANDMEMBER_SUB_STRATEGY_MUL > size) { if (count*SRANDMEMBER_SUB_STRATEGY_MUL > size) {
setTypeIterator *si; setTypeIterator *si;
/* Add all the elements into the temporary dictionary. */ /* Add all the elements into the temporary dictionary. */
si = setTypeInitIterator(set); si = setTypeInitIterator(set);
dictExpand(d, size);
while ((encoding = setTypeNext(si,&ele,&llele)) != -1) { while ((encoding = setTypeNext(si,&ele,&llele)) != -1) {
int retval = DICT_ERR; int retval = DICT_ERR;
if (encoding == OBJ_ENCODING_INTSET) { if (encoding == OBJ_ENCODING_INTSET) {
retval = dictAdd(d,sdsfromlonglong(llele),NULL); retval = dictAdd(d,sdsfromlonglong(llele),NULL);
} else { } else {
retval = dictAdd(d,sdsdup(ele),NULL); retval = dictAdd(d,sdsdup(ele),NULL);
} }
serverAssert(retval == DICT_OK); serverAssert(retval == DICT_OK);
} }
skipping to change at line 765 skipping to change at line 775
} }
/* CASE 4: We have a big set compared to the requested number of elements. /* CASE 4: We have a big set compared to the requested number of elements.
* In this case we can simply get random elements from the set and add * In this case we can simply get random elements from the set and add
* to the temporary set, trying to eventually get enough unique elements * to the temporary set, trying to eventually get enough unique elements
* to reach the specified count. */ * to reach the specified count. */
else { else {
unsigned long added = 0; unsigned long added = 0;
sds sdsele; sds sdsele;
dictExpand(d, count);
while (added < count) { while (added < count) {
encoding = setTypeRandomElement(set,&ele,&llele); encoding = setTypeRandomElement(set,&ele,&llele);
if (encoding == OBJ_ENCODING_INTSET) { if (encoding == OBJ_ENCODING_INTSET) {
sdsele = sdsfromlonglong(llele); sdsele = sdsfromlonglong(llele);
} else { } else {
sdsele = sdsdup(ele); sdsele = sdsdup(ele);
} }
/* Try to add the object to the dictionary. If it already exists /* Try to add the object to the dictionary. If it already exists
* free it, otherwise increment the number of objects we have * free it, otherwise increment the number of objects we have
* in the result dictionary. */ * in the result dictionary. */
skipping to change at line 787 skipping to change at line 798
else else
sdsfree(sdsele); sdsfree(sdsele);
} }
} }
/* CASE 3 & 4: send the result to the user. */ /* CASE 3 & 4: send the result to the user. */
{ {
dictIterator *di; dictIterator *di;
dictEntry *de; dictEntry *de;
addReplySetLen(c,count); addReplyArrayLen(c,count);
di = dictGetIterator(d); di = dictGetIterator(d);
while((de = dictNext(di)) != NULL) while((de = dictNext(di)) != NULL)
addReplyBulkSds(c,dictGetKey(de)); addReplyBulkSds(c,dictGetKey(de));
dictReleaseIterator(di); dictReleaseIterator(di);
dictRelease(d); dictRelease(d);
} }
} }
/* SRANDMEMBER [<count>] */ /* SRANDMEMBER [<count>] */
void srandmemberCommand(client *c) { void srandmemberCommand(client *c) {
 End of changes. 11 change blocks. 
11 lines changed or deleted 22 lines changed or added

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