| 1056 | |
| 1057 | int prepareClientToWrite(client *c, bool fAsync); |
| 1058 | void keysCommand(client *c) { |
| 1059 | sds pattern = szFromObj(c->argv[1]); |
| 1060 | |
| 1061 | const redisDbPersistentDataSnapshot *snapshot = nullptr; |
| 1062 | if (!(c->flags & (CLIENT_MULTI | CLIENT_BLOCKED | CLIENT_DENY_BLOCKING)) && !(serverTL->in_eval || serverTL->in_exec)) |
| 1063 | snapshot = c->db->createSnapshot(c->mvccCheckpoint, true /* fOptional */); |
| 1064 | if (snapshot != nullptr) |
| 1065 | { |
| 1066 | sds patternCopy = sdsdup(pattern); |
| 1067 | aeEventLoop *el = serverTL->el; |
| 1068 | blockClient(c, BLOCKED_ASYNC); |
| 1069 | redisDb *db = c->db; |
| 1070 | g_pserver->asyncworkqueue->AddWorkFunction([el, c, db, patternCopy, snapshot]{ |
| 1071 | keysCommandCore(c, snapshot, patternCopy); |
| 1072 | sdsfree(patternCopy); |
| 1073 | aePostFunction(el, [c, db, snapshot]{ |
| 1074 | aeReleaseLock(); // we need to lock with coordination of the client |
| 1075 | |
| 1076 | std::unique_lock<decltype(c->lock)> lock(c->lock); |
| 1077 | AeLocker locker; |
| 1078 | locker.arm(c); |
| 1079 | |
| 1080 | unblockClient(c); |
| 1081 | |
| 1082 | locker.disarm(); |
| 1083 | lock.unlock(); |
| 1084 | db->endSnapshotAsync(snapshot); |
| 1085 | aeAcquireLock(); |
| 1086 | }); |
| 1087 | }); |
| 1088 | } |
| 1089 | else |
| 1090 | { |
| 1091 | keysCommandCore(c, c->db, pattern); |
| 1092 | } |
| 1093 | } |
| 1094 | |
| 1095 | /* This callback is used by scanGenericCommand in order to collect elements |
| 1096 | * returned by the dictionary iterator into a list. */ |
nothing calls this directly
no test coverage detected