| 1347 | } |
| 1348 | |
| 1349 | void scanFilterAndReply(client *c, list *keys, sds pat, sds type, int use_pattern, robj_roptr o, unsigned long cursor) |
| 1350 | { |
| 1351 | listNode *node, *nextnode; |
| 1352 | int patlen = (pat != nullptr) ? sdslen(pat) : 0; |
| 1353 | |
| 1354 | /* Step 3: Filter elements. */ |
| 1355 | node = listFirst(keys); |
| 1356 | while (node) { |
| 1357 | robj *kobj = (robj*)listNodeValue(node); |
| 1358 | nextnode = listNextNode(node); |
| 1359 | int filter = 0; |
| 1360 | |
| 1361 | /* Filter element if it does not match the pattern. */ |
| 1362 | if (use_pattern) { |
| 1363 | if (filterKey(kobj, pat, patlen)) |
| 1364 | filter = 1; |
| 1365 | } |
| 1366 | |
| 1367 | /* Filter an element if it isn't the type we want. */ |
| 1368 | if (!filter && o == nullptr && type){ |
| 1369 | robj_roptr typecheck = lookupKeyReadWithFlags(c->db, kobj, LOOKUP_NOTOUCH); |
| 1370 | const char* typeT = getObjectTypeName(typecheck); |
| 1371 | if (strcasecmp((char*) type, typeT)) filter = 1; |
| 1372 | } |
| 1373 | |
| 1374 | /* Filter element if it is an expired key. */ |
| 1375 | if (!filter && o == nullptr && expireIfNeeded(c->db, kobj)) filter = 1; |
| 1376 | |
| 1377 | /* Remove the element and its associated value if needed. */ |
| 1378 | if (filter) { |
| 1379 | decrRefCount(kobj); |
| 1380 | listDelNode(keys, node); |
| 1381 | } |
| 1382 | |
| 1383 | /* If this is a hash or a sorted set, we have a flat list of |
| 1384 | * key-value elements, so if this element was filtered, remove the |
| 1385 | * value, or skip it if it was not filtered: we only match keys. */ |
| 1386 | if (o && (o->type == OBJ_ZSET || o->type == OBJ_HASH)) { |
| 1387 | node = nextnode; |
| 1388 | serverAssert(node); /* assertion for valgrind (avoid NPD) */ |
| 1389 | nextnode = listNextNode(node); |
| 1390 | if (filter) { |
| 1391 | kobj = (robj*)listNodeValue(node); |
| 1392 | decrRefCount(kobj); |
| 1393 | listDelNode(keys, node); |
| 1394 | } |
| 1395 | } |
| 1396 | node = nextnode; |
| 1397 | } |
| 1398 | |
| 1399 | /* Step 4: Reply to the client. */ |
| 1400 | addReplyArrayLen(c, 2); |
| 1401 | addReplyBulkLongLong(c,cursor); |
| 1402 | |
| 1403 | addReplyArrayLen(c, listLength(keys)); |
| 1404 | while ((node = listFirst(keys)) != NULL) { |
| 1405 | robj *kobj = (robj*)listNodeValue(node); |
| 1406 | addReplyBulk(c, kobj); |
no test coverage detected