This function is called just before entering the event loop, in the hope * we can just write the replies to the client output buffer without any * need to use a syscall in order to install the writable event handler, * get it called, and so forth. */
| 2065 | * need to use a syscall in order to install the writable event handler, |
| 2066 | * get it called, and so forth. */ |
| 2067 | int handleClientsWithPendingWrites(int iel, int aof_state) { |
| 2068 | int processed = 0; |
| 2069 | serverAssert(iel == (serverTL - g_pserver->rgthreadvar)); |
| 2070 | |
| 2071 | if (listLength(serverTL->clients_pending_asyncwrite)) |
| 2072 | { |
| 2073 | AeLocker locker; |
| 2074 | locker.arm(nullptr); |
| 2075 | ProcessPendingAsyncWrites(); |
| 2076 | } |
| 2077 | |
| 2078 | int ae_flags = AE_WRITABLE|AE_WRITE_THREADSAFE; |
| 2079 | /* For the fsync=always policy, we want that a given FD is never |
| 2080 | * served for reading and writing in the same event loop iteration, |
| 2081 | * so that in the middle of receiving the query, and serving it |
| 2082 | * to the client, we'll call beforeSleep() that will do the |
| 2083 | * actual fsync of AOF to disk. AE_BARRIER ensures that. */ |
| 2084 | if (aof_state == AOF_ON && |
| 2085 | g_pserver->aof_fsync == AOF_FSYNC_ALWAYS) |
| 2086 | { |
| 2087 | ae_flags |= AE_BARRIER; |
| 2088 | } |
| 2089 | |
| 2090 | std::unique_lock<fastlock> lockf(g_pserver->rgthreadvar[iel].lockPendingWrite); |
| 2091 | auto vec = std::move(g_pserver->rgthreadvar[iel].clients_pending_write); |
| 2092 | lockf.unlock(); |
| 2093 | processed += (int)vec.size(); |
| 2094 | |
| 2095 | for (client *c : vec) { |
| 2096 | serverAssertDebug(FCorrectThread(c)); |
| 2097 | |
| 2098 | uint64_t flags = c->flags.fetch_and(~CLIENT_PENDING_WRITE, std::memory_order_relaxed); |
| 2099 | |
| 2100 | /* If a client is protected, don't do anything, |
| 2101 | * that may trigger write error or recreate handler. */ |
| 2102 | if ((flags & CLIENT_PROTECTED) && !(flags & CLIENT_SLAVE)) continue; |
| 2103 | |
| 2104 | /* Don't write to clients that are going to be closed anyway. */ |
| 2105 | if (c->flags & CLIENT_CLOSE_ASAP) continue; |
| 2106 | |
| 2107 | /* Try to write buffers to the client socket, unless its a replica in multithread mode */ |
| 2108 | if (writeToClient(c,0) == C_ERR) |
| 2109 | { |
| 2110 | if (c->flags & CLIENT_CLOSE_ASAP) |
| 2111 | { |
| 2112 | AeLocker ae; |
| 2113 | ae.arm(nullptr); |
| 2114 | freeClient(c); // writeToClient will only async close, but there's no need to wait |
| 2115 | } |
| 2116 | continue; |
| 2117 | } |
| 2118 | |
| 2119 | /* If after the synchronous writes above we still have data to |
| 2120 | * output to the client, we need to install the writable handler. */ |
| 2121 | std::unique_lock<decltype(c->lock)> lock(c->lock); |
| 2122 | if (clientHasPendingReplies(c)) { |
| 2123 | if (connSetWriteHandlerWithBarrier(c->conn, sendReplyToClient, ae_flags, true) == C_ERR) { |
| 2124 | freeClientAsync(c); |
no test coverage detected