PFCOUNT var -> approximated cardinality of set. */
| 1228 | |
| 1229 | /* PFCOUNT var -> approximated cardinality of set. */ |
| 1230 | void pfcountCommand(client *c) { |
| 1231 | robj *o; |
| 1232 | struct hllhdr *hdr; |
| 1233 | uint64_t card; |
| 1234 | |
| 1235 | /* Case 1: multi-key keys, cardinality of the union. |
| 1236 | * |
| 1237 | * When multiple keys are specified, PFCOUNT actually computes |
| 1238 | * the cardinality of the merge of the N HLLs specified. */ |
| 1239 | if (c->argc > 2) { |
| 1240 | uint8_t max[HLL_HDR_SIZE+HLL_REGISTERS], *registers; |
| 1241 | int j; |
| 1242 | |
| 1243 | /* Compute an HLL with M[i] = MAX(M[i]_j). */ |
| 1244 | memset(max,0,sizeof(max)); |
| 1245 | hdr = (struct hllhdr*) max; |
| 1246 | hdr->encoding = HLL_RAW; /* Special internal-only encoding. */ |
| 1247 | registers = max + HLL_HDR_SIZE; |
| 1248 | for (j = 1; j < c->argc; j++) { |
| 1249 | /* Check type and size. */ |
| 1250 | robj_roptr o = lookupKeyRead(c->db,c->argv[j]); |
| 1251 | if (o == nullptr) continue; /* Assume empty HLL for non existing var.*/ |
| 1252 | if (isHLLObjectOrReply(c,o) != C_OK) return; |
| 1253 | |
| 1254 | /* Merge with this HLL with our 'max' HLL by setting max[i] |
| 1255 | * to MAX(max[i],hll[i]). */ |
| 1256 | if (hllMerge(registers,HLL_REGISTERS,o) == C_ERR) { |
| 1257 | addReplyError(c,invalid_hll_err); |
| 1258 | return; |
| 1259 | } |
| 1260 | } |
| 1261 | |
| 1262 | /* Compute cardinality of the resulting set. */ |
| 1263 | addReplyLongLong(c,hllCount(hdr,NULL)); |
| 1264 | return; |
| 1265 | } |
| 1266 | |
| 1267 | /* Case 2: cardinality of the single HLL. |
| 1268 | * |
| 1269 | * The user specified a single key. Either return the cached value |
| 1270 | * or compute one and update the cache. */ |
| 1271 | o = lookupKeyWrite(c->db,c->argv[1]); |
| 1272 | if (o == NULL) { |
| 1273 | /* No key? Cardinality is zero since no element was added, otherwise |
| 1274 | * we would have a key as HLLADD creates it as a side effect. */ |
| 1275 | addReply(c,shared.czero); |
| 1276 | } else { |
| 1277 | if (isHLLObjectOrReply(c,o) != C_OK) return; |
| 1278 | o = dbUnshareStringValue(c->db,c->argv[1],o); |
| 1279 | |
| 1280 | /* Check if the cached cardinality is valid. */ |
| 1281 | hdr = (hllhdr*)ptrFromObj(o); |
| 1282 | if (HLL_VALID_CACHE(hdr)) { |
| 1283 | /* Just return the cached value. */ |
| 1284 | card = (uint64_t)hdr->card[0]; |
| 1285 | card |= (uint64_t)hdr->card[1] << 8; |
| 1286 | card |= (uint64_t)hdr->card[2] << 16; |
| 1287 | card |= (uint64_t)hdr->card[3] << 24; |
nothing calls this directly
no test coverage detected