Call() is the core of Redis execution of a command. * * The following flags can be passed: * CMD_CALL_NONE No flags. * CMD_CALL_SLOWLOG Check command speed and log in the slow log if needed. * CMD_CALL_STATS Populate command stats. * CMD_CALL_PROPAGATE_AOF Append command to AOF if it modified the dataset * or if the client flags are forcing propag
| 4492 | * |
| 4493 | */ |
| 4494 | void call(client *c, int flags) { |
| 4495 | long long dirty; |
| 4496 | monotime call_timer; |
| 4497 | int client_old_flags = c->flags; |
| 4498 | struct redisCommand *real_cmd = c->cmd; |
| 4499 | serverAssert(((flags & CMD_CALL_ASYNC) && (c->cmd->flags & CMD_READONLY)) || GlobalLocksAcquired()); |
| 4500 | |
| 4501 | /* We need to transfer async writes before a client's repl state gets changed. Otherwise |
| 4502 | we won't be able to propogate them correctly. */ |
| 4503 | if (c->cmd->flags & CMD_CATEGORY_REPLICATION) { |
| 4504 | flushReplBacklogToClients(); |
| 4505 | ProcessPendingAsyncWrites(); |
| 4506 | } |
| 4507 | |
| 4508 | /* Initialization: clear the flags that must be set by the command on |
| 4509 | * demand, and initialize the array for additional commands propagation. */ |
| 4510 | c->flags &= ~(CLIENT_FORCE_AOF|CLIENT_FORCE_REPL|CLIENT_PREVENT_PROP); |
| 4511 | redisOpArray prev_also_propagate; |
| 4512 | if (!(flags & CMD_CALL_ASYNC)) { |
| 4513 | prev_also_propagate = g_pserver->also_propagate; |
| 4514 | redisOpArrayInit(&g_pserver->also_propagate); |
| 4515 | } |
| 4516 | |
| 4517 | /* Call the command. */ |
| 4518 | dirty = g_pserver->dirty; |
| 4519 | serverTL->prev_err_count = serverTL->stat_total_error_replies; |
| 4520 | g_pserver->fixed_time_expire++; |
| 4521 | incrementMvccTstamp(); |
| 4522 | elapsedStart(&call_timer); |
| 4523 | try { |
| 4524 | c->cmd->proc(c); |
| 4525 | } catch (robj_roptr o) { |
| 4526 | addReply(c, o); |
| 4527 | } catch (robj *o) { |
| 4528 | addReply(c, o); |
| 4529 | } catch (const char *sz) { |
| 4530 | addReplyError(c, sz); |
| 4531 | } |
| 4532 | serverTL->commandsExecuted++; |
| 4533 | const long duration = elapsedUs(call_timer); |
| 4534 | c->duration = duration; |
| 4535 | if (flags & CMD_CALL_ASYNC) |
| 4536 | dirty = 0; // dirty is bogus in this case as there's no synchronization |
| 4537 | else |
| 4538 | dirty = g_pserver->dirty-dirty; |
| 4539 | if (dirty < 0) dirty = 0; |
| 4540 | |
| 4541 | if (dirty) |
| 4542 | c->mvccCheckpoint = getMvccTstamp(); |
| 4543 | |
| 4544 | /* Update failed command calls if required. |
| 4545 | * We leverage a static variable (prev_err_count) to retain |
| 4546 | * the counter across nested function calls and avoid logging |
| 4547 | * the same error twice. */ |
| 4548 | if ((serverTL->stat_total_error_replies - serverTL->prev_err_count) > 0) { |
| 4549 | real_cmd->failed_calls++; |
| 4550 | } |
| 4551 |
no test coverage detected