Defrag helper for sorted set. * Update the robj pointer, defrag the skiplist struct and return the new score * reference. We may not access oldele pointer (not even the pointer stored in * the skiplist), as it was already freed. Newele may be null, in which case we * only need to defrag the skiplist, but not update the obj pointer. * When return value is non-NULL, it is the score reference th
| 202 | * When return value is non-NULL, it is the score reference that must be updated |
| 203 | * in the dict record. */ |
| 204 | double *zslDefrag(zskiplist *zsl, double score, sds oldele, sds newele) { |
| 205 | zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x, *newx; |
| 206 | int i; |
| 207 | sds ele = newele? newele: oldele; |
| 208 | |
| 209 | /* find the skiplist node referring to the object that was moved, |
| 210 | * and all pointers that need to be updated if we'll end up moving the skiplist node. */ |
| 211 | x = zsl->header; |
| 212 | for (i = zsl->level-1; i >= 0; i--) { |
| 213 | while (x->level[i].forward && |
| 214 | x->level[i].forward->ele != oldele && /* make sure not to access the |
| 215 | ->obj pointer if it matches |
| 216 | oldele */ |
| 217 | (x->level[i].forward->score < score || |
| 218 | (x->level[i].forward->score == score && |
| 219 | sdscmp(x->level[i].forward->ele,ele) < 0))) |
| 220 | x = x->level[i].forward; |
| 221 | update[i] = x; |
| 222 | } |
| 223 | |
| 224 | /* update the robj pointer inside the skip list record. */ |
| 225 | x = x->level[0].forward; |
| 226 | serverAssert(x && score == x->score && x->ele==oldele); |
| 227 | if (newele) |
| 228 | x->ele = newele; |
| 229 | |
| 230 | /* try to defrag the skiplist record itself */ |
| 231 | newx = activeDefragAlloc(x); |
| 232 | if (newx) { |
| 233 | zslUpdateNode(zsl, x, newx, update); |
| 234 | return &newx->score; |
| 235 | } |
| 236 | return NULL; |
| 237 | } |
| 238 | |
| 239 | /* Defrag helper for sorted set. |
| 240 | * Defrag a single dict entry key name, and corresponding skiplist struct */ |
no test coverage detected