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