| 58 | } |
| 59 | |
| 60 | Status Execute([[maybe_unused]] engine::Context &ctx, Server *srv, Connection *conn, std::string *output) override { |
| 61 | INFO( |
| 62 | "Slave {}, listening port: {}, announce ip: {} asks for synchronization " |
| 63 | "with next sequence: {}, replication id: {}, and local sequence: {}", |
| 64 | conn->GetAddr(), conn->GetListeningPort(), conn->GetAnnounceIP(), next_repl_seq_, |
| 65 | (replica_replid_.length() ? replica_replid_ : "not supported"), srv->storage->LatestSeqNumber()); |
| 66 | bool need_full_sync = false; |
| 67 | |
| 68 | // Check replication id of the last sequence log |
| 69 | if (new_psync_ && srv->GetConfig()->use_rsid_psync) { |
| 70 | std::string replid_in_wal = srv->storage->GetReplIdFromWalBySeq(next_repl_seq_ - 1); |
| 71 | INFO("Replication id in WAL: {}", replid_in_wal); |
| 72 | |
| 73 | // We check replication id only when WAL has this sequence, since there may be no WAL, |
| 74 | // Or WAL may have nothing when starting from db of old version kvrocks. |
| 75 | if (replid_in_wal.length() == kReplIdLength && replid_in_wal != replica_replid_) { |
| 76 | *output = "wrong replication id of the last log"; |
| 77 | need_full_sync = true; |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | // Check Log sequence |
| 82 | if (!need_full_sync && !checkWALBoundary(srv->storage, next_repl_seq_).IsOK()) { |
| 83 | *output = "sequence out of range, please use fullsync"; |
| 84 | need_full_sync = true; |
| 85 | } |
| 86 | |
| 87 | if (need_full_sync) { |
| 88 | srv->stats.IncrPSyncErrCount(); |
| 89 | return {Status::RedisExecErr, *output}; |
| 90 | } |
| 91 | |
| 92 | // Server would spawn a new thread to sync the batch, and connection would |
| 93 | // be taken over, so should never trigger any event in worker thread. |
| 94 | conn->Detach(); |
| 95 | conn->EnableFlag(redis::Connection::kSlave); |
| 96 | auto s = util::SockSetBlocking(conn->GetFD(), 1); |
| 97 | if (!s.IsOK()) { |
| 98 | conn->EnableFlag(redis::Connection::kCloseAsync); |
| 99 | return s.Prefixed("failed to set blocking mode on socket"); |
| 100 | } |
| 101 | |
| 102 | srv->stats.IncrPSyncOKCount(); |
| 103 | s = srv->AddSlave(conn, next_repl_seq_); |
| 104 | if (!s.IsOK()) { |
| 105 | std::string err = redis::Error(s); |
| 106 | s = util::SockSend(conn->GetFD(), err, conn->GetBufferEvent()); |
| 107 | if (!s.IsOK()) { |
| 108 | WARN("failed to send error message to the replica: {}", s.Msg()); |
| 109 | } |
| 110 | conn->EnableFlag(redis::Connection::kCloseAsync); |
| 111 | WARN("Failed to add replica: {} to start incremental syncing", conn->GetAddr()); |
| 112 | } else { |
| 113 | INFO("New replica: {} was added, start incremental syncing", conn->GetAddr()); |
| 114 | } |
| 115 | return s; |
| 116 | } |
| 117 |
nothing calls this directly
no test coverage detected