refactor of asyncCommand to include snapshot creation
Former-commit-id: c0908362162b5f2834b90cd9ce84fd1ee6768834
This commit is contained in:
parent
3a988e0232
commit
d658891bf0
@ -4952,24 +4952,35 @@ bool client::postFunction(std::function<void(client *)> fn, bool fLock) {
|
|||||||
}, fLock) == AE_OK;
|
}, fLock) == AE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void client::asyncCommand(std::function<void()> &&preFn, std::function<void()> &&mainFn, std::function<void()> &&postFn) {
|
bool client::asyncCommand(std::function<void *(const redisDbPersistentDataSnapshot *)> &&preFn,
|
||||||
|
std::function<void(const redisDbPersistentDataSnapshot *, void *)> &&mainFn,
|
||||||
|
std::function<void(const redisDbPersistentDataSnapshot *, void *)> &&postFn)
|
||||||
|
{
|
||||||
|
const redisDbPersistentDataSnapshot *snapshot = nullptr;
|
||||||
|
if (!(this->flags & (CLIENT_MULTI | CLIENT_BLOCKED)))
|
||||||
|
snapshot = this->db->createSnapshot(this->mvccCheckpoint, false /* fOptional */);
|
||||||
|
if (snapshot == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
aeEventLoop *el = serverTL->el;
|
aeEventLoop *el = serverTL->el;
|
||||||
blockClient(this, BLOCKED_ASYNC);
|
blockClient(this, BLOCKED_ASYNC);
|
||||||
g_pserver->asyncworkqueue->AddWorkFunction([el, this, preFn, mainFn, postFn] {
|
g_pserver->asyncworkqueue->AddWorkFunction([el, this, preFn, mainFn, postFn, snapshot] {
|
||||||
preFn();
|
void *preData = preFn(snapshot);
|
||||||
aePostFunction(el, [this, mainFn, postFn] {
|
aePostFunction(el, [this, mainFn, postFn, snapshot, preData] {
|
||||||
aeReleaseLock();
|
aeReleaseLock();
|
||||||
std::unique_lock<decltype(this->lock)> lock(this->lock);
|
std::unique_lock<decltype(this->lock)> lock(this->lock);
|
||||||
AeLocker locker;
|
AeLocker locker;
|
||||||
locker.arm(this);
|
locker.arm(this);
|
||||||
unblockClient(this);
|
unblockClient(this);
|
||||||
mainFn();
|
mainFn(snapshot, preData);
|
||||||
locker.disarm();
|
locker.disarm();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
postFn();
|
postFn(snapshot, preData);
|
||||||
|
this->db->endSnapshotAsync(snapshot);
|
||||||
aeAcquireLock();
|
aeAcquireLock();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ====================== Error lookup and execution ===================== */
|
/* ====================== Error lookup and execution ===================== */
|
||||||
|
@ -1661,7 +1661,9 @@ struct client {
|
|||||||
// post a function from a non-client thread to run on its client thread
|
// post a function from a non-client thread to run on its client thread
|
||||||
bool postFunction(std::function<void(client *)> fn, bool fLock = true);
|
bool postFunction(std::function<void(client *)> fn, bool fLock = true);
|
||||||
size_t argv_len_sum() const;
|
size_t argv_len_sum() const;
|
||||||
void asyncCommand(std::function<void()> &&preFn, std::function<void()> &&mainFn, std::function<void()> &&postFn);
|
bool asyncCommand(std::function<void *(const redisDbPersistentDataSnapshot *)> &&preFn,
|
||||||
|
std::function<void(const redisDbPersistentDataSnapshot *, void *)> &&mainFn,
|
||||||
|
std::function<void(const redisDbPersistentDataSnapshot *, void *)> &&postFn);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct saveparam {
|
struct saveparam {
|
||||||
|
@ -524,27 +524,24 @@ void getrangeCommand(client *c) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mgetCommand(client *c) {
|
list *mgetKeysFromClient(client *c) {
|
||||||
// Do async version for large number of arguments
|
|
||||||
if (c->argc > 100) {
|
|
||||||
const redisDbPersistentDataSnapshot *snapshot = nullptr;
|
|
||||||
if (!(c->flags & (CLIENT_MULTI | CLIENT_BLOCKED)))
|
|
||||||
snapshot = c->db->createSnapshot(c->mvccCheckpoint, false /* fOptional */);
|
|
||||||
if (snapshot != nullptr) {
|
|
||||||
list *keys = listCreate();
|
list *keys = listCreate();
|
||||||
redisDb *db = c->db;
|
|
||||||
c->asyncCommand(
|
|
||||||
[c, keys] {
|
|
||||||
for (int j = 1; j < c->argc; j++) {
|
for (int j = 1; j < c->argc; j++) {
|
||||||
incrRefCount(c->argv[j]);
|
incrRefCount(c->argv[j]);
|
||||||
listAddNodeTail(keys, c->argv[j]);
|
listAddNodeTail(keys, c->argv[j]);
|
||||||
}
|
}
|
||||||
},
|
return keys;
|
||||||
[c, keys, snapshot] {
|
}
|
||||||
|
|
||||||
|
void mgetCore(client *c, list *keys, const redisDbPersistentDataSnapshot *snapshot = nullptr) {
|
||||||
addReplyArrayLen(c,listLength(keys));
|
addReplyArrayLen(c,listLength(keys));
|
||||||
listNode *ln = listFirst(keys);
|
listNode *ln = listFirst(keys);
|
||||||
while (ln != nullptr) {
|
while (ln != nullptr) {
|
||||||
robj_roptr o = snapshot->find_cached_threadsafe(szFromObj((robj*)listNodeValue(ln))).val();
|
robj_roptr o;
|
||||||
|
if (snapshot)
|
||||||
|
o = snapshot->find_cached_threadsafe(szFromObj((robj*)listNodeValue(ln))).val();
|
||||||
|
else
|
||||||
|
o = lookupKeyRead(c->db,(robj*)listNodeValue(ln));
|
||||||
if (o == nullptr || o->type != OBJ_STRING) {
|
if (o == nullptr || o->type != OBJ_STRING) {
|
||||||
addReplyNull(c);
|
addReplyNull(c);
|
||||||
} else {
|
} else {
|
||||||
@ -552,30 +549,34 @@ void mgetCommand(client *c) {
|
|||||||
}
|
}
|
||||||
ln = ln->next;
|
ln = ln->next;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
[keys, snapshot, db] {
|
|
||||||
db->endSnapshotAsync(snapshot);
|
void mgetClearKeys(list *keys) {
|
||||||
listSetFreeMethod(keys,decrRefCountVoid);
|
listSetFreeMethod(keys,decrRefCountVoid);
|
||||||
listRelease(keys);
|
listRelease(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mgetCommand(client *c) {
|
||||||
|
// Do async version for large number of arguments
|
||||||
|
if (c->argc > 100) {
|
||||||
|
if (c->asyncCommand(
|
||||||
|
[c] (const redisDbPersistentDataSnapshot *snapshot) {
|
||||||
|
return mgetKeysFromClient(c);
|
||||||
|
},
|
||||||
|
[c] (const redisDbPersistentDataSnapshot *snapshot, void *keys) {
|
||||||
|
mgetCore(c, (list *)keys, snapshot);
|
||||||
|
},
|
||||||
|
[] (const redisDbPersistentDataSnapshot *snapshot, void *keys) {
|
||||||
|
mgetClearKeys((list *)keys);
|
||||||
}
|
}
|
||||||
);
|
)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addReplyArrayLen(c,c->argc-1);
|
list *keys = mgetKeysFromClient(c);
|
||||||
for (int j = 1; j < c->argc; j++) {
|
mgetCore(c, keys);
|
||||||
robj_roptr o = lookupKeyRead(c->db,c->argv[j]);
|
mgetClearKeys(keys);
|
||||||
if (o == nullptr) {
|
|
||||||
addReplyNull(c);
|
|
||||||
} else {
|
|
||||||
if (o->type != OBJ_STRING) {
|
|
||||||
addReplyNull(c);
|
|
||||||
} else {
|
|
||||||
addReplyBulk(c,o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void msetGenericCommand(client *c, int nx) {
|
void msetGenericCommand(client *c, int nx) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user