MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / writeToClient

Function writeToClient

src/networking.cpp:1821–1965  ·  view source on GitHub ↗

Write data in output buffers to client. Return C_OK if the client * is still valid after the call, C_ERR if it was freed because of some * error. If handler_installed is set, it will attempt to clear the * write event. * * This function is called by threads, but always with handler_installed * set to 0. So when handler_installed is set to 0 the function must be * thread safe. */

Source from the content-addressed store, hash-verified

1819 * set to 0. So when handler_installed is set to 0 the function must be
1820 * thread safe. */
1821int writeToClient(client *c, int handler_installed) {
1822 /* Update total number of writes on server */
1823 g_pserver->stat_total_writes_processed.fetch_add(1, std::memory_order_relaxed);
1824
1825 ssize_t nwritten = 0, totwritten = 0;
1826 clientReplyBlock *o;
1827 serverAssertDebug(FCorrectThread(c));
1828
1829 std::unique_lock<decltype(c->lock)> lock(c->lock);
1830
1831 /* We can only directly read from the replication backlog if the client
1832 is a replica, so only attempt to do so if that's the case. */
1833 if (c->flags & CLIENT_SLAVE && !(c->flags & CLIENT_MONITOR) && c->replstate == SLAVE_STATE_ONLINE) {
1834 std::unique_lock<fastlock> repl_backlog_lock (g_pserver->repl_backlog_lock);
1835 // Ensure all writes to the repl backlog are visible
1836 std::atomic_thread_fence(std::memory_order_acquire);
1837
1838 while (clientHasPendingReplies(c)) {
1839 long long repl_end_idx = getReplIndexFromOffset(c->repl_end_off);
1840 serverAssert(c->repl_curr_off != -1);
1841
1842 if (c->repl_curr_off != c->repl_end_off){
1843 long long repl_curr_idx = getReplIndexFromOffset(c->repl_curr_off);
1844 long long nwritten2ndStage = 0; /* How much was written from the start of the replication backlog
1845 * in the event of a wrap around write */
1846 /* normal case with no wrap around */
1847 if (repl_end_idx >= repl_curr_idx){
1848 nwritten = connWrite(c->conn, g_pserver->repl_backlog + repl_curr_idx, repl_end_idx - repl_curr_idx);
1849 /* wrap around case */
1850 } else {
1851 nwritten = connWrite(c->conn, g_pserver->repl_backlog + repl_curr_idx, g_pserver->repl_backlog_size - repl_curr_idx);
1852 /* only attempt wrapping if we write the correct number of bytes */
1853 if (nwritten == g_pserver->repl_backlog_size - repl_curr_idx){
1854 nwritten2ndStage = connWrite(c->conn, g_pserver->repl_backlog, repl_end_idx);
1855 if (nwritten2ndStage != -1)
1856 nwritten += nwritten2ndStage;
1857 }
1858 }
1859
1860 /* only increment bytes if an error didn't occur */
1861 if (nwritten > 0){
1862 totwritten += nwritten;
1863 c->repl_curr_off += nwritten;
1864 serverAssert(c->repl_curr_off <= c->repl_end_off);
1865 }
1866
1867 /* If the second part of a write didn't go through, we still need to register that */
1868 if (nwritten2ndStage == -1) nwritten = -1;
1869 if (nwritten == -1)
1870 break;
1871 } else {
1872 break;
1873 }
1874 }
1875 } else {
1876 while(clientHasPendingReplies(c)) {
1877 if (c->bufpos > 0) {
1878 auto bufpos = c->bufpos;

Callers 4

sendReplyToClientFunction · 0.85
flushSlavesOutputBuffersFunction · 0.85
ldbEndSessionFunction · 0.85

Calls 14

FCorrectThreadFunction · 0.85
clientHasPendingRepliesFunction · 0.85
getReplIndexFromOffsetFunction · 0.85
connWriteFunction · 0.85
listDelNodeFunction · 0.85
zmalloc_used_memoryFunction · 0.85
connGetStateFunction · 0.85
serverLogFunction · 0.85
connGetLastErrorFunction · 0.85
freeClientAsyncFunction · 0.85
connSetWriteHandlerFunction · 0.85
unlockMethod · 0.45

Tested by

no test coverage detected