| 1024 | #define HRANDFIELD_RANDOM_SAMPLE_LIMIT 1000 |
| 1025 | |
| 1026 | void hrandfieldWithCountCommand(client *c, long l, int withvalues) { |
| 1027 | unsigned long count, size; |
| 1028 | int uniq = 1; |
| 1029 | robj_roptr hash; |
| 1030 | |
| 1031 | if ((hash = lookupKeyReadOrReply(c,c->argv[1],shared.emptyarray)) |
| 1032 | == nullptr || checkType(c,hash,OBJ_HASH)) return; |
| 1033 | size = hashTypeLength(hash); |
| 1034 | |
| 1035 | if(l >= 0) { |
| 1036 | count = (unsigned long) l; |
| 1037 | } else { |
| 1038 | count = -l; |
| 1039 | uniq = 0; |
| 1040 | } |
| 1041 | |
| 1042 | /* If count is zero, serve it ASAP to avoid special cases later. */ |
| 1043 | if (count == 0) { |
| 1044 | addReply(c,shared.emptyarray); |
| 1045 | return; |
| 1046 | } |
| 1047 | |
| 1048 | /* CASE 1: The count was negative, so the extraction method is just: |
| 1049 | * "return N random elements" sampling the whole set every time. |
| 1050 | * This case is trivial and can be served without auxiliary data |
| 1051 | * structures. This case is the only one that also needs to return the |
| 1052 | * elements in random order. */ |
| 1053 | if (!uniq || count == 1) { |
| 1054 | if (withvalues && c->resp == 2) |
| 1055 | addReplyArrayLen(c, count*2); |
| 1056 | else |
| 1057 | addReplyArrayLen(c, count); |
| 1058 | if (hash->encoding == OBJ_ENCODING_HT) { |
| 1059 | sds key, value; |
| 1060 | while (count--) { |
| 1061 | dictEntry *de = dictGetFairRandomKey((dict*)ptrFromObj(hash)); |
| 1062 | key = (sds)dictGetKey(de); |
| 1063 | value = (sds)dictGetVal(de); |
| 1064 | if (withvalues && c->resp > 2) |
| 1065 | addReplyArrayLen(c,2); |
| 1066 | addReplyBulkCBuffer(c, key, sdslen(key)); |
| 1067 | if (withvalues) |
| 1068 | addReplyBulkCBuffer(c, value, sdslen(value)); |
| 1069 | if (c->flags & CLIENT_CLOSE_ASAP) |
| 1070 | break; |
| 1071 | } |
| 1072 | } else if (hash->encoding == OBJ_ENCODING_ZIPLIST) { |
| 1073 | ziplistEntry *keys, *vals = NULL; |
| 1074 | unsigned long limit, sample_count; |
| 1075 | limit = count > HRANDFIELD_RANDOM_SAMPLE_LIMIT ? HRANDFIELD_RANDOM_SAMPLE_LIMIT : count; |
| 1076 | keys = (ziplistEntry*)zmalloc(sizeof(ziplistEntry)*limit); |
| 1077 | if (withvalues) |
| 1078 | vals = (ziplistEntry*)zmalloc(sizeof(ziplistEntry)*limit); |
| 1079 | while (count) { |
| 1080 | sample_count = count > limit ? limit : count; |
| 1081 | count -= sample_count; |
| 1082 | ziplistRandomPairs((unsigned char*)ptrFromObj(hash), sample_count, keys, vals); |
| 1083 | harndfieldReplyWithZiplist(c, sample_count, keys, vals); |
no test coverage detected