| 5609 | void _clientAsyncReplyBufferReserve(client *c, size_t len); |
| 5610 | |
| 5611 | void flushReplBacklogToClients() |
| 5612 | { |
| 5613 | serverAssert(GlobalLocksAcquired()); |
| 5614 | /* If we have the repl backlog lock, we will deadlock */ |
| 5615 | serverAssert(!g_pserver->repl_backlog_lock.fOwnLock()); |
| 5616 | if (g_pserver->repl_batch_offStart < 0) |
| 5617 | return; |
| 5618 | |
| 5619 | if (g_pserver->repl_batch_offStart != g_pserver->master_repl_offset) { |
| 5620 | bool fAsyncWrite = false; |
| 5621 | long long min_offset = LLONG_MAX; |
| 5622 | // Ensure no overflow |
| 5623 | serverAssert(g_pserver->repl_batch_offStart < g_pserver->master_repl_offset); |
| 5624 | if (g_pserver->master_repl_offset - g_pserver->repl_batch_offStart > g_pserver->repl_backlog_size) { |
| 5625 | // We overflowed |
| 5626 | listIter li; |
| 5627 | listNode *ln; |
| 5628 | listRewind(g_pserver->slaves, &li); |
| 5629 | while ((ln = listNext(&li))) { |
| 5630 | client *c = (client*)listNodeValue(ln); |
| 5631 | sds sdsClient = catClientInfoString(sdsempty(),c); |
| 5632 | freeClientAsync(c); |
| 5633 | serverLog(LL_WARNING,"Client %s scheduled to be closed ASAP for overcoming of output buffer limits.", sdsClient); |
| 5634 | sdsfree(sdsClient); |
| 5635 | } |
| 5636 | goto LDone; |
| 5637 | } |
| 5638 | |
| 5639 | // Ensure no overflow if we get here |
| 5640 | serverAssert(g_pserver->master_repl_offset - g_pserver->repl_batch_offStart <= g_pserver->repl_backlog_size); |
| 5641 | serverAssert(g_pserver->repl_batch_idxStart != g_pserver->repl_backlog_idx); |
| 5642 | |
| 5643 | // Repl backlog writes must become visible to all threads at this point |
| 5644 | std::atomic_thread_fence(std::memory_order_release); |
| 5645 | |
| 5646 | listIter li; |
| 5647 | listNode *ln; |
| 5648 | listRewind(g_pserver->slaves, &li); |
| 5649 | /* We don't actually write any data in this function since we send data |
| 5650 | * directly from the replication backlog to replicas in writeToClient. |
| 5651 | * |
| 5652 | * What we do however, is set the end offset of each replica here. This way, |
| 5653 | * future calls to writeToClient will know up to where in the replication |
| 5654 | * backlog is valid for writing. */ |
| 5655 | while ((ln = listNext(&li))) { |
| 5656 | client *replica = (client*)listNodeValue(ln); |
| 5657 | |
| 5658 | if (!canFeedReplicaReplBuffer(replica)) continue; |
| 5659 | if (replica->flags & CLIENT_CLOSE_ASAP) continue; |
| 5660 | |
| 5661 | std::unique_lock<fastlock> ul(replica->lock); |
| 5662 | if (!FCorrectThread(replica)) |
| 5663 | fAsyncWrite = true; |
| 5664 | |
| 5665 | /* We should have set the repl_curr_off when synchronizing, so it shouldn't be -1 here */ |
| 5666 | serverAssert(replica->repl_curr_off != -1); |
| 5667 | |
| 5668 | min_offset = std::min(min_offset, replica->repl_curr_off); |
no test coverage detected