| 460 | #define SPOP_MOVE_STRATEGY_MUL 5 |
| 461 | |
| 462 | void spopWithCountCommand(client *c) { |
| 463 | long l; |
| 464 | unsigned long count, size; |
| 465 | robj *set; |
| 466 | |
| 467 | /* Get the count argument */ |
| 468 | if (getPositiveLongFromObjectOrReply(c,c->argv[2],&l,NULL) != C_OK) return; |
| 469 | count = (unsigned long) l; |
| 470 | |
| 471 | /* Make sure a key with the name inputted exists, and that it's type is |
| 472 | * indeed a set. Otherwise, return nil */ |
| 473 | if ((set = lookupKeyWriteOrReply(c,c->argv[1],shared.emptyset[c->resp])) |
| 474 | == NULL || checkType(c,set,OBJ_SET)) return; |
| 475 | |
| 476 | /* If count is zero, serve an empty set ASAP to avoid special |
| 477 | * cases later. */ |
| 478 | if (count == 0) { |
| 479 | addReply(c,shared.emptyset[c->resp]); |
| 480 | return; |
| 481 | } |
| 482 | |
| 483 | size = setTypeSize(set); |
| 484 | |
| 485 | /* Generate an SPOP keyspace notification */ |
| 486 | notifyKeyspaceEvent(NOTIFY_SET,"spop",c->argv[1],c->db->id); |
| 487 | g_pserver->dirty += (count >= size) ? size : count; |
| 488 | |
| 489 | /* CASE 1: |
| 490 | * The number of requested elements is greater than or equal to |
| 491 | * the number of elements inside the set: simply return the whole set. */ |
| 492 | if (count >= size) { |
| 493 | /* We just return the entire set */ |
| 494 | sunionDiffGenericCommand(c,c->argv+1,1,NULL,SET_OP_UNION); |
| 495 | |
| 496 | /* Delete the set as it is now empty */ |
| 497 | dbDelete(c->db,c->argv[1]); |
| 498 | notifyKeyspaceEvent(NOTIFY_GENERIC,"del",c->argv[1],c->db->id); |
| 499 | |
| 500 | /* Propagate this command as a DEL operation */ |
| 501 | rewriteClientCommandVector(c,2,shared.del,c->argv[1]); |
| 502 | signalModifiedKey(c,c->db,c->argv[1]); |
| 503 | return; |
| 504 | } |
| 505 | |
| 506 | /* Case 2 and 3 require to replicate SPOP as a set of SREM commands. |
| 507 | * Prepare our replication argument vector. Also send the array length |
| 508 | * which is common to both the code paths. */ |
| 509 | robj *propargv[3]; |
| 510 | propargv[0] = shared.srem; |
| 511 | propargv[1] = c->argv[1]; |
| 512 | addReplySetLen(c,count); |
| 513 | |
| 514 | /* Common iteration vars. */ |
| 515 | const char *sdsele; |
| 516 | robj *objele; |
| 517 | int encoding; |
| 518 | int64_t llele = 0; |
| 519 | unsigned long remaining = size-count; /* Elements left after SPOP. */ |
no test coverage detected