Remove fPendingReplicaWrite flag which can instead be calculated on demand
Former-commit-id: ae26afd13f955eb230b5c2cab20ec90db9b714ad
This commit is contained in:
parent
4ac475ea20
commit
53d7d09f07
@ -158,7 +158,6 @@ client *createClient(connection *conn, int iel) {
|
|||||||
c->flags = 0;
|
c->flags = 0;
|
||||||
c->fPendingAsyncWrite = FALSE;
|
c->fPendingAsyncWrite = FALSE;
|
||||||
c->fPendingAsyncWriteHandler = FALSE;
|
c->fPendingAsyncWriteHandler = FALSE;
|
||||||
c->fPendingReplicaWrite = FALSE;
|
|
||||||
c->ctime = c->lastinteraction = g_pserver->unixtime;
|
c->ctime = c->lastinteraction = g_pserver->unixtime;
|
||||||
/* If the default user does not require authentication, the user is
|
/* If the default user does not require authentication, the user is
|
||||||
* directly authenticated. */
|
* directly authenticated. */
|
||||||
@ -318,7 +317,7 @@ int prepareClientToWrite(client *c) {
|
|||||||
|
|
||||||
/* Schedule the client to write the output buffers to the socket, unless
|
/* Schedule the client to write the output buffers to the socket, unless
|
||||||
* it should already be setup to do so (it has already pending data). */
|
* it should already be setup to do so (it has already pending data). */
|
||||||
if (!fAsync && !clientHasPendingReplies(c) && !c->fPendingReplicaWrite) clientInstallWriteHandler(c);
|
if (!fAsync && (c->flags & CLIENT_SLAVE || !clientHasPendingReplies(c))) clientInstallWriteHandler(c);
|
||||||
if (fAsync && !(c->fPendingAsyncWrite)) clientInstallAsyncWriteHandler(c);
|
if (fAsync && !(c->fPendingAsyncWrite)) clientInstallAsyncWriteHandler(c);
|
||||||
|
|
||||||
/* Authorize the caller to queue in the output buffer of this client. */
|
/* Authorize the caller to queue in the output buffer of this client. */
|
||||||
@ -1132,7 +1131,7 @@ void copyClientOutputBuffer(client *dst, client *src) {
|
|||||||
/* Return true if the specified client has pending reply buffers to write to
|
/* Return true if the specified client has pending reply buffers to write to
|
||||||
* the socket. */
|
* the socket. */
|
||||||
int clientHasPendingReplies(client *c) {
|
int clientHasPendingReplies(client *c) {
|
||||||
return (c->bufpos || listLength(c->reply));
|
return (c->bufpos || listLength(c->reply) || c->FPendingReplicaWrite());
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::atomic<int> rgacceptsInFlight[MAX_EVENT_LOOPS];
|
static std::atomic<int> rgacceptsInFlight[MAX_EVENT_LOOPS];
|
||||||
@ -1785,6 +1784,42 @@ int writeToClient(client *c, int handler_installed) {
|
|||||||
|
|
||||||
std::unique_lock<decltype(c->lock)> lock(c->lock);
|
std::unique_lock<decltype(c->lock)> lock(c->lock);
|
||||||
|
|
||||||
|
/* We can only directly read from the replication backlog if the client
|
||||||
|
is a replica, so only attempt to do so if that's the case. */
|
||||||
|
if (c->flags & CLIENT_SLAVE && !(c->flags & CLIENT_MONITOR)) {
|
||||||
|
std::unique_lock<fastlock> repl_backlog_lock (g_pserver->repl_backlog_lock);
|
||||||
|
long long repl_end_idx = getReplIndexFromOffset(c->repl_end_off);
|
||||||
|
serverAssert(c->repl_curr_off != -1);
|
||||||
|
|
||||||
|
if (c->repl_curr_off != c->repl_end_off){
|
||||||
|
long long repl_curr_idx = getReplIndexFromOffset(c->repl_curr_off);
|
||||||
|
long long nwritten2ndStage = 0; /* How much was written from the start of the replication backlog
|
||||||
|
* in the event of a wrap around write */
|
||||||
|
/* normal case with no wrap around */
|
||||||
|
if (repl_end_idx >= repl_curr_idx){
|
||||||
|
nwritten = connWrite(c->conn, g_pserver->repl_backlog + repl_curr_idx, repl_end_idx - repl_curr_idx);
|
||||||
|
/* wrap around case */
|
||||||
|
} else {
|
||||||
|
nwritten = connWrite(c->conn, g_pserver->repl_backlog + repl_curr_idx, g_pserver->repl_backlog_size - repl_curr_idx);
|
||||||
|
/* only attempt wrapping if we write the correct number of bytes */
|
||||||
|
if (nwritten == g_pserver->repl_backlog_size - repl_curr_idx){
|
||||||
|
nwritten2ndStage = connWrite(c->conn, g_pserver->repl_backlog, repl_end_idx);
|
||||||
|
if (nwritten2ndStage != -1)
|
||||||
|
nwritten += nwritten2ndStage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only increment bytes if an error didn't occur */
|
||||||
|
if (nwritten > 0){
|
||||||
|
totwritten += nwritten;
|
||||||
|
c->repl_curr_off += nwritten;
|
||||||
|
serverAssert(c->repl_curr_off <= c->repl_end_off);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the second part of a write didn't go through, we still need to register that */
|
||||||
|
if (nwritten2ndStage == -1) nwritten = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
while(clientHasPendingReplies(c)) {
|
while(clientHasPendingReplies(c)) {
|
||||||
serverAssert(!(c->flags & CLIENT_SLAVE) || c->flags & CLIENT_MONITOR);
|
serverAssert(!(c->flags & CLIENT_SLAVE) || c->flags & CLIENT_MONITOR);
|
||||||
if (c->bufpos > 0) {
|
if (c->bufpos > 0) {
|
||||||
@ -1840,47 +1875,6 @@ int writeToClient(client *c, int handler_installed) {
|
|||||||
zmalloc_used_memory() < g_pserver->maxmemory) &&
|
zmalloc_used_memory() < g_pserver->maxmemory) &&
|
||||||
!(c->flags & CLIENT_SLAVE)) break;
|
!(c->flags & CLIENT_SLAVE)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We can only directly read from the replication backlog if the client
|
|
||||||
is a replica, so only attempt to do so if that's the case. */
|
|
||||||
if (c->flags & CLIENT_SLAVE && !(c->flags & CLIENT_MONITOR)) {
|
|
||||||
|
|
||||||
std::unique_lock<fastlock> repl_backlog_lock (g_pserver->repl_backlog_lock);
|
|
||||||
long long repl_end_idx = getReplIndexFromOffset(c->repl_end_off);
|
|
||||||
serverAssert(c->repl_curr_off != -1);
|
|
||||||
|
|
||||||
if (c->repl_curr_off != c->repl_end_off){
|
|
||||||
long long repl_curr_idx = getReplIndexFromOffset(c->repl_curr_off);
|
|
||||||
long long nwritten2ndStage = 0; /* How much was written from the start of the replication backlog
|
|
||||||
* in the event of a wrap around write */
|
|
||||||
/* normal case with no wrap around */
|
|
||||||
if (repl_end_idx >= repl_curr_idx){
|
|
||||||
nwritten = connWrite(c->conn, g_pserver->repl_backlog + repl_curr_idx, repl_end_idx - repl_curr_idx);
|
|
||||||
/* wrap around case */
|
|
||||||
} else {
|
|
||||||
nwritten = connWrite(c->conn, g_pserver->repl_backlog + repl_curr_idx, g_pserver->repl_backlog_size - repl_curr_idx);
|
|
||||||
/* only attempt wrapping if we write the correct number of bytes */
|
|
||||||
if (nwritten == g_pserver->repl_backlog_size - repl_curr_idx){
|
|
||||||
nwritten2ndStage = connWrite(c->conn, g_pserver->repl_backlog, repl_end_idx);
|
|
||||||
if (nwritten2ndStage != -1)
|
|
||||||
nwritten += nwritten2ndStage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* only increment bytes if an error didn't occur */
|
|
||||||
if (nwritten > 0){
|
|
||||||
totwritten += nwritten;
|
|
||||||
c->repl_curr_off += nwritten;
|
|
||||||
serverAssert(c->repl_curr_off <= c->repl_end_off);
|
|
||||||
/* If the client's current offset matches the last offset it can read from, there is no pending write */
|
|
||||||
if (c->repl_curr_off == c->repl_end_off){
|
|
||||||
c->fPendingReplicaWrite = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the second part of a write didn't go through, we still need to register that */
|
|
||||||
if (nwritten2ndStage == -1) nwritten = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pserver->stat_net_output_bytes += totwritten;
|
g_pserver->stat_net_output_bytes += totwritten;
|
||||||
@ -1900,7 +1894,7 @@ int writeToClient(client *c, int handler_installed) {
|
|||||||
* We just rely on data / pings received for timeout detection. */
|
* We just rely on data / pings received for timeout detection. */
|
||||||
if (!(c->flags & CLIENT_MASTER)) c->lastinteraction = g_pserver->unixtime;
|
if (!(c->flags & CLIENT_MASTER)) c->lastinteraction = g_pserver->unixtime;
|
||||||
}
|
}
|
||||||
if (!clientHasPendingReplies(c) && !c->fPendingReplicaWrite) {
|
if (!clientHasPendingReplies(c)) {
|
||||||
c->sentlen = 0;
|
c->sentlen = 0;
|
||||||
if (handler_installed) connSetWriteHandler(c->conn, NULL);
|
if (handler_installed) connSetWriteHandler(c->conn, NULL);
|
||||||
|
|
||||||
@ -2080,7 +2074,7 @@ int handleClientsWithPendingWrites(int iel, int aof_state) {
|
|||||||
|
|
||||||
/* If after the synchronous writes above we still have data to
|
/* If after the synchronous writes above we still have data to
|
||||||
* output to the client, we need to install the writable handler. */
|
* output to the client, we need to install the writable handler. */
|
||||||
if (clientHasPendingReplies(c) || c->fPendingReplicaWrite) {
|
if (clientHasPendingReplies(c)) {
|
||||||
if (connSetWriteHandlerWithBarrier(c->conn, sendReplyToClient, ae_flags, true) == C_ERR) {
|
if (connSetWriteHandlerWithBarrier(c->conn, sendReplyToClient, ae_flags, true) == C_ERR) {
|
||||||
freeClientAsync(c);
|
freeClientAsync(c);
|
||||||
}
|
}
|
||||||
@ -3705,7 +3699,7 @@ void rewriteClientCommandArgument(client *c, int i, robj *newval) {
|
|||||||
/* In the case of a replica client, writes to said replica are using data from the replication backlog
|
/* In the case of a replica client, writes to said replica are using data from the replication backlog
|
||||||
* as opposed to it's own internal buffer, this number should keep track of that */
|
* as opposed to it's own internal buffer, this number should keep track of that */
|
||||||
unsigned long getClientReplicationBacklogSharedUsage(client *c) {
|
unsigned long getClientReplicationBacklogSharedUsage(client *c) {
|
||||||
return (!(c->flags & CLIENT_SLAVE) || !c->fPendingReplicaWrite ) ? 0 : g_pserver->master_repl_offset - c->repl_curr_off;
|
return (!(c->flags & CLIENT_SLAVE) || !c->FPendingReplicaWrite() ) ? 0 : g_pserver->master_repl_offset - c->repl_curr_off;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function returns the number of bytes that Redis is
|
/* This function returns the number of bytes that Redis is
|
||||||
|
@ -722,7 +722,6 @@ long long addReplyReplicationBacklog(client *c, long long offset) {
|
|||||||
|
|
||||||
/* Force the partial sync to be queued */
|
/* Force the partial sync to be queued */
|
||||||
prepareClientToWrite(c);
|
prepareClientToWrite(c);
|
||||||
c->fPendingReplicaWrite = true;
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -4974,11 +4973,8 @@ void flushReplBacklogToClients()
|
|||||||
replica->repl_end_off = g_pserver->master_repl_offset;
|
replica->repl_end_off = g_pserver->master_repl_offset;
|
||||||
|
|
||||||
/* Only if the there isn't already a pending write do we prepare the client to write */
|
/* Only if the there isn't already a pending write do we prepare the client to write */
|
||||||
if (!replica->fPendingReplicaWrite){
|
|
||||||
serverAssert(replica->repl_curr_off != g_pserver->master_repl_offset);
|
serverAssert(replica->repl_curr_off != g_pserver->master_repl_offset);
|
||||||
prepareClientToWrite(replica);
|
prepareClientToWrite(replica);
|
||||||
replica->fPendingReplicaWrite = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (fAsyncWrite)
|
if (fAsyncWrite)
|
||||||
|
@ -1594,7 +1594,6 @@ struct client {
|
|||||||
* when sending data to this replica. */
|
* when sending data to this replica. */
|
||||||
long long repl_end_off = -1; /* Replication offset to write to, stored in the replica, as opposed to using the global offset
|
long long repl_end_off = -1; /* Replication offset to write to, stored in the replica, as opposed to using the global offset
|
||||||
* to prevent needing the global lock */
|
* to prevent needing the global lock */
|
||||||
int fPendingReplicaWrite; /* Is there a write queued for this replica? */
|
|
||||||
|
|
||||||
char replid[CONFIG_RUN_ID_SIZE+1]; /* Master replication ID (if master). */
|
char replid[CONFIG_RUN_ID_SIZE+1]; /* Master replication ID (if master). */
|
||||||
int slave_listening_port; /* As configured with: REPLCONF listening-port */
|
int slave_listening_port; /* As configured with: REPLCONF listening-port */
|
||||||
@ -1657,6 +1656,10 @@ struct client {
|
|||||||
robj **argv;
|
robj **argv;
|
||||||
size_t argv_len_sumActive = 0;
|
size_t argv_len_sumActive = 0;
|
||||||
|
|
||||||
|
bool FPendingReplicaWrite() const {
|
||||||
|
return repl_curr_off != repl_end_off;
|
||||||
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user