| 657 | #define SRANDMEMBER_SUB_STRATEGY_MUL 3 |
| 658 | |
| 659 | void srandmemberWithCountCommand(client *c) { |
| 660 | long l; |
| 661 | unsigned long count, size; |
| 662 | int uniq = 1; |
| 663 | robj *set; |
| 664 | sds ele; |
| 665 | int64_t llele; |
| 666 | int encoding; |
| 667 | |
| 668 | dict *d; |
| 669 | |
| 670 | if (getLongFromObjectOrReply(c,c->argv[2],&l,NULL) != C_OK) return; |
| 671 | if (l >= 0) { |
| 672 | count = (unsigned long) l; |
| 673 | } else { |
| 674 | /* A negative count means: return the same elements multiple times |
| 675 | * (i.e. don't remove the extracted element after every extraction). */ |
| 676 | count = -l; |
| 677 | uniq = 0; |
| 678 | } |
| 679 | |
| 680 | if ((set = lookupKeyReadOrReply(c,c->argv[1],shared.emptyarray)) |
| 681 | == NULL || checkType(c,set,OBJ_SET)) return; |
| 682 | size = setTypeSize(set); |
| 683 | |
| 684 | /* If count is zero, serve it ASAP to avoid special cases later. */ |
| 685 | if (count == 0) { |
| 686 | addReply(c,shared.emptyarray); |
| 687 | return; |
| 688 | } |
| 689 | |
| 690 | /* CASE 1: The count was negative, so the extraction method is just: |
| 691 | * "return N random elements" sampling the whole set every time. |
| 692 | * This case is trivial and can be served without auxiliary data |
| 693 | * structures. This case is the only one that also needs to return the |
| 694 | * elements in random order. */ |
| 695 | if (!uniq || count == 1) { |
| 696 | addReplyArrayLen(c,count); |
| 697 | while(count--) { |
| 698 | encoding = setTypeRandomElement(set,&ele,&llele); |
| 699 | if (encoding == OBJ_ENCODING_INTSET) { |
| 700 | addReplyBulkLongLong(c,llele); |
| 701 | } else { |
| 702 | addReplyBulkCBuffer(c,ele,sdslen(ele)); |
| 703 | } |
| 704 | } |
| 705 | return; |
| 706 | } |
| 707 | |
| 708 | /* CASE 2: |
| 709 | * The number of requested elements is greater than the number of |
| 710 | * elements inside the set: simply return the whole set. */ |
| 711 | if (count >= size) { |
| 712 | setTypeIterator *si; |
| 713 | addReplyArrayLen(c,size); |
| 714 | si = setTypeInitIterator(set); |
| 715 | while ((encoding = setTypeNext(si,&ele,&llele)) != -1) { |
| 716 | if (encoding == OBJ_ENCODING_INTSET) { |
no test coverage detected