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