PFMERGE dest src1 src2 src3 ... srcN => OK */
| 1308 | |
| 1309 | /* PFMERGE dest src1 src2 src3 ... srcN => OK */ |
| 1310 | void pfmergeCommand(client *c) { |
| 1311 | uint8_t max[HLL_REGISTERS]; |
| 1312 | struct hllhdr *hdr; |
| 1313 | int j; |
| 1314 | int use_dense = 0; /* Use dense representation as target? */ |
| 1315 | |
| 1316 | /* Compute an HLL with M[i] = MAX(M[i]_j). |
| 1317 | * We store the maximum into the max array of registers. We'll write |
| 1318 | * it to the target variable later. */ |
| 1319 | memset(max,0,sizeof(max)); |
| 1320 | for (j = 1; j < c->argc; j++) { |
| 1321 | /* Check type and size. */ |
| 1322 | robj *o = lookupKeyRead(c->db,c->argv[j]); |
| 1323 | if (o == NULL) continue; /* Assume empty HLL for non existing var. */ |
| 1324 | if (isHLLObjectOrReply(c,o) != C_OK) return; |
| 1325 | |
| 1326 | /* If at least one involved HLL is dense, use the dense representation |
| 1327 | * as target ASAP to save time and avoid the conversion step. */ |
| 1328 | hdr = o->ptr; |
| 1329 | if (hdr->encoding == HLL_DENSE) use_dense = 1; |
| 1330 | |
| 1331 | /* Merge with this HLL with our 'max' HLL by setting max[i] |
| 1332 | * to MAX(max[i],hll[i]). */ |
| 1333 | if (hllMerge(max,o) == C_ERR) { |
| 1334 | addReplyError(c,invalid_hll_err); |
| 1335 | return; |
| 1336 | } |
| 1337 | } |
| 1338 | |
| 1339 | /* Create / unshare the destination key's value if needed. */ |
| 1340 | robj *o = lookupKeyWrite(c->db,c->argv[1]); |
| 1341 | if (o == NULL) { |
| 1342 | /* Create the key with a string value of the exact length to |
| 1343 | * hold our HLL data structure. sdsnewlen() when NULL is passed |
| 1344 | * is guaranteed to return bytes initialized to zero. */ |
| 1345 | o = createHLLObject(); |
| 1346 | dbAdd(c->db,c->argv[1],o); |
| 1347 | } else { |
| 1348 | /* If key exists we are sure it's of the right type/size |
| 1349 | * since we checked when merging the different HLLs, so we |
| 1350 | * don't check again. */ |
| 1351 | o = dbUnshareStringValue(c->db,c->argv[1],o); |
| 1352 | } |
| 1353 | |
| 1354 | /* Convert the destination object to dense representation if at least |
| 1355 | * one of the inputs was dense. */ |
| 1356 | if (use_dense && hllSparseToDense(o) == C_ERR) { |
| 1357 | addReplyError(c,invalid_hll_err); |
| 1358 | return; |
| 1359 | } |
| 1360 | |
| 1361 | /* Write the resulting HLL to the destination HLL registers and |
| 1362 | * invalidate the cached value. */ |
| 1363 | for (j = 0; j < HLL_REGISTERS; j++) { |
| 1364 | if (max[j] == 0) continue; |
| 1365 | hdr = o->ptr; |
| 1366 | switch(hdr->encoding) { |
| 1367 | case HLL_DENSE: hllDenseSet(hdr->registers,j,max[j]); break; |
nothing calls this directly
no test coverage detected