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

Function resizeReplicationBacklog

src/replication.cpp:264–337  ·  view source on GitHub ↗

This function is called when the user modifies the replication backlog * size at runtime. It is up to the function to both update the * g_pserver->repl_backlog_size and to resize the buffer and setup it so that * it contains the same data as the previous one (possibly less data, but * the most recent bytes, or the same data and more free space in case the * buffer is enlarged). */

Source from the content-addressed store, hash-verified

262 * the most recent bytes, or the same data and more free space in case the
263 * buffer is enlarged). */
264void resizeReplicationBacklog(long long newsize) {
265 if (newsize < CONFIG_REPL_BACKLOG_MIN_SIZE)
266 newsize = CONFIG_REPL_BACKLOG_MIN_SIZE;
267 if (g_pserver->repl_backlog_size == newsize) return;
268
269 if (g_pserver->repl_backlog != NULL) {
270 std::unique_lock<fastlock> repl_backlog_lock(g_pserver->repl_backlog_lock);
271 /* What we actually do is to flush the old buffer and realloc a new
272 * empty one. It will refill with new data incrementally.
273 * The reason is that copying a few gigabytes adds latency and even
274 * worse often we need to alloc additional space before freeing the
275 * old buffer. */
276
277 /* get the critical client size, i.e. the size of the data unflushed to clients */
278 long long earliest_off = g_pserver->repl_lowest_off.load();
279
280 if (earliest_off != -1) {
281 char *backlog = nullptr;
282 newsize = std::max(newsize, g_pserver->master_repl_offset - earliest_off);
283
284 if (cserver.repl_backlog_disk_size != 0) {
285 if (newsize > g_pserver->repl_backlog_config_size || cserver.force_backlog_disk) {
286 if (g_pserver->repl_backlog == g_pserver->repl_backlog_disk)
287 return; // Can't do anything more
288 serverLog(LL_NOTICE, "Switching to disk backed replication backlog due to exceeding memory limits");
289 backlog = g_pserver->repl_backlog_disk;
290 newsize = cserver.repl_backlog_disk_size;
291 }
292 }
293
294 // We need to keep critical data so we can't shrink less than the hot data in the buffer
295 if (backlog == nullptr)
296 backlog = (char*)zmalloc(newsize);
297 g_pserver->repl_backlog_histlen = g_pserver->master_repl_offset - earliest_off;
298 long long earliest_idx = getReplIndexFromOffset(earliest_off);
299
300 if (g_pserver->repl_backlog_idx >= earliest_idx) {
301 auto cbActiveBacklog = g_pserver->repl_backlog_idx - earliest_idx;
302 memcpy(backlog, g_pserver->repl_backlog + earliest_idx, cbActiveBacklog);
303 serverAssert(g_pserver->repl_backlog_histlen == cbActiveBacklog);
304 } else {
305 auto cbPhase1 = g_pserver->repl_backlog_size - earliest_idx;
306 memcpy(backlog, g_pserver->repl_backlog + earliest_idx, cbPhase1);
307 memcpy(backlog + cbPhase1, g_pserver->repl_backlog, g_pserver->repl_backlog_idx);
308 auto cbActiveBacklog = cbPhase1 + g_pserver->repl_backlog_idx;
309 serverAssert(g_pserver->repl_backlog_histlen == cbActiveBacklog);
310 }
311 if (g_pserver->repl_backlog != g_pserver->repl_backlog_disk)
312 zfree(g_pserver->repl_backlog);
313 else
314 serverLog(LL_NOTICE, "Returning to memory backed replication backlog");
315 g_pserver->repl_backlog = backlog;
316 g_pserver->repl_backlog_idx = g_pserver->repl_backlog_histlen;
317 if (g_pserver->repl_batch_idxStart >= 0) {
318 g_pserver->repl_batch_idxStart -= earliest_idx;
319 if (g_pserver->repl_batch_idxStart < 0)
320 g_pserver->repl_batch_idxStart += g_pserver->repl_backlog_size;
321 }

Callers 3

feedReplicationBacklogFunction · 0.85
trimReplicationBacklogFunction · 0.85
updateReplBacklogSizeFunction · 0.85

Calls 4

serverLogFunction · 0.85
zmallocFunction · 0.85
getReplIndexFromOffsetFunction · 0.85
zfreeFunction · 0.85

Tested by

no test coverage detected