| 166 | } |
| 167 | |
| 168 | void DatabaseReplicatedDDLWorker::initializeReplication() |
| 169 | { |
| 170 | /// Check if we need to recover replica. |
| 171 | /// Invariant: replica is lost if it's log_ptr value is less then max_log_ptr - logs_to_keep. |
| 172 | |
| 173 | auto zookeeper = getZooKeeper(); |
| 174 | |
| 175 | /// Create "active" node (remove previous one if necessary) |
| 176 | String active_path = fs::path(database->replica_path) / "active"; |
| 177 | String active_id = toString(ServerUUID::get()); |
| 178 | |
| 179 | LOG_TRACE(log, "Trying to delete emhemeral active node: active_path={}, active_id={}", active_path, active_id); |
| 180 | |
| 181 | zookeeper->deleteEphemeralNodeIfContentMatches( |
| 182 | active_path, |
| 183 | [&active_id](const std::string & actual_content) |
| 184 | { |
| 185 | if (actual_content.ends_with(DatabaseReplicated::REPLICA_UNSYNCED_MARKER)) |
| 186 | return active_id == actual_content.substr(0, actual_content.size() - strlen(DatabaseReplicated::REPLICA_UNSYNCED_MARKER)); |
| 187 | return active_id == actual_content; |
| 188 | }); |
| 189 | bool first_initialization = active_node_holder == nullptr; |
| 190 | if (active_node_holder) |
| 191 | active_node_holder->setAlreadyRemoved(); |
| 192 | active_node_holder.reset(); |
| 193 | |
| 194 | String log_ptr_str = zookeeper->get(database->replica_path + "/log_ptr"); |
| 195 | UInt32 our_log_ptr = parse<UInt32>(log_ptr_str); |
| 196 | UInt32 max_log_ptr = parse<UInt32>(zookeeper->get(database->zookeeper_path + "/max_log_ptr")); |
| 197 | logs_to_keep = parse<UInt32>(zookeeper->get(database->zookeeper_path + "/logs_to_keep")); |
| 198 | |
| 199 | UInt64 digest = 0; |
| 200 | String digest_str; |
| 201 | UInt64 local_digest = 0; |
| 202 | if (zookeeper->tryGet(database->replica_path + "/digest", digest_str)) |
| 203 | { |
| 204 | digest = parse<UInt64>(digest_str); |
| 205 | std::lock_guard lock{database->metadata_mutex}; |
| 206 | local_digest = database->tables_metadata_digest; |
| 207 | } |
| 208 | else |
| 209 | { |
| 210 | LOG_WARNING(log, "Did not find digest in ZooKeeper, creating it"); |
| 211 | /// Database was created by old ClickHouse versions, let's create the node |
| 212 | std::lock_guard lock{database->metadata_mutex}; |
| 213 | digest = local_digest = database->tables_metadata_digest; |
| 214 | digest_str = toString(digest); |
| 215 | zookeeper->create(database->replica_path + "/digest", digest_str, zkutil::CreateMode::Persistent); |
| 216 | } |
| 217 | |
| 218 | LOG_TRACE(log, "Trying to initialize replication: our_log_ptr={}, max_log_ptr={}, local_digest={}, zk_digest={}", |
| 219 | our_log_ptr, max_log_ptr, local_digest, digest); |
| 220 | |
| 221 | bool is_new_replica = our_log_ptr == 0; |
| 222 | bool lost_according_to_log_ptr = our_log_ptr + logs_to_keep < max_log_ptr; |
| 223 | bool lost_according_to_digest = database->db_settings[DatabaseReplicatedSetting::check_consistency] && local_digest != digest; |
| 224 | |
| 225 | if (is_new_replica || lost_according_to_log_ptr || lost_according_to_digest) |
nothing calls this directly
no test coverage detected