// called when a background save (including checkpoint) has finished with result. void arc_bgsave_done_handler (int ok) { client *c; struct redis_stat buf; // ----------------------------------------------- // handle "save", "bgsave", "cronsave", "seqsave" // ----------------------------------------------- if (arc.cluster_mode && arc.checkpoint_slots == NULL) { if (ok != C_OK) { // already logged } else if (smr_seq_ckpted (arc.smr_conn, arc.seqnum_before_bgsave) != 0) { serverLog (LL_WARNING, "Failed to notify checkpointed sequence to smr"); server.lastbgsave_status = C_ERR; } else { serverLog (LL_NOTICE, "Checkpointed sequence is sent to SMR, seqnum:%lld", arc.seqnum_before_bgsave); arc.last_bgsave_seqnum = arc.seqnum_before_bgsave; } } // -------------------- // handle "checkpoint" // -------------------- if (arc.checkpoint_slots == NULL) { return; } arc.checkpoint_seqnum = arc.seqnum_before_bgsave; sdsfree (arc.checkpoint_slots); arc.checkpoint_slots = NULL; c = arc.checkpoint_client; arc.checkpoint_client = NULL; if (c == NULL) { return; } if (ok != C_OK) { serverLog (LL_WARNING, "CHECKPOINT failed. background child returned an error"); freeClient (c); return; } if ((c->smr->ckptdbfd = open (arc.checkpoint_filename, O_RDONLY)) == -1 || redis_fstat (c->smr->ckptdbfd, &buf) == -1) { freeClient (c); serverLog (LL_WARNING, "CHECKPOINT failed. Can't open/stat DB after CHECKPOINT: %s", strerror (errno)); return; } c->smr->ckptdboff = 0; c->smr->ckptdbsize = buf.st_size; c->replstate = SLAVE_STATE_SEND_BULK; aeDeleteFileEvent (server.el, c->fd, AE_WRITABLE); if (aeCreateFileEvent (server.el, c->fd, AE_WRITABLE, send_bulk_to_target, c) == AE_ERR) { freeClient (c); } }
/* Main */ int clusterMain (int argc, char **argv) { long long teid; redisLog (REDIS_WARNING, "Server started, Redis version " REDIS_VERSION); #ifdef __linux__ linuxOvercommitMemoryWarning (); #endif loadDataFromDisk (); server.last_bgsave_seqnum = server.smr_seqnum; /* Warning the user about suspicious maxmemory setting. */ if (server.maxmemory > 0 && server.maxmemory < 1024 * 1024) { redisLog (REDIS_WARNING, "WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?", server.maxmemory); } smrConnect (); /* initializeCron for handling sigterm */ teid = aeCreateTimeEvent (server.el, 1, initializeCron, NULL, NULL); aeMain (server.el); aeDeleteTimeEvent (server.el, teid); if (server.need_rckpt) { redisLog (REDIS_NOTICE, "Need more checkpoint from %s:%d", server.ckpt_host, server.ckpt_port); smrDisconnect (); server.smr_init_flags = SMR_INIT_RCKPT; if (getdump (server.ckpt_host, server.ckpt_port, server.rdb_filename, "0-8191", REDIS_GETDUMP_DEFAULT_NET_LIMIT_MB) != REDIS_OK) { exit (1); } emptyDb (NULL); loadDataFromDisk (); server.last_bgsave_seqnum = server.smr_seqnum; smrConnect (); aeMain (server.el); } if (!server.is_ready) { redisLog (REDIS_WARNING, "Invalid initialization state"); exit (1); } if (server.last_bgsave_seqnum) { if (smr_seq_ckpted (server.smr_conn, server.last_bgsave_seqnum) != 0) { redisLog (REDIS_WARNING, "Failed to notify checkpointed sequence to smr"); exit (1); } else { redisLog (REDIS_NOTICE, "Checkpointed sequence is sent to SMR, seqnum:%lld", server.last_bgsave_seqnum); } } server.smr_seqnum_reset = 0; server.last_catchup_check_mstime = mstime (); server.smr_init_flags = SMR_INIT_CATCHUP_PHASE1; if (smr_catchup (server.smr_conn) == -1) { redisLog (REDIS_WARNING, "Failed to catchup errno(%d)", errno); exit (1); } server.smr_init_flags = SMR_INIT_CATCHUP_PHASE2; checkSmrCatchup (); aeSetBeforeSleepProc (server.el, beforeSleep); aeMain (server.el); aeDeleteEventLoop (server.el); exit (0); }