MCPcopy Create free account
hub / github.com/ByConity/ByConity / initAndCheckTask

Method initAndCheckTask

src/Databases/DatabaseReplicatedWorker.cpp:191–298  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

189}
190
191DDLTaskPtr DatabaseReplicatedDDLWorker::initAndCheckTask(const String & entry_name, String & out_reason, const ZooKeeperPtr & zookeeper)
192{
193 {
194 std::lock_guard lock{mutex};
195 if (current_task < entry_name)
196 {
197 current_task = entry_name;
198 wait_current_task_change.notify_all();
199 }
200 }
201
202 UInt32 our_log_ptr = parse<UInt32>(zookeeper->get(fs::path(database->replica_path) / "log_ptr"));
203 UInt32 entry_num = DatabaseReplicatedTask::getLogEntryNumber(entry_name);
204
205 if (entry_num <= our_log_ptr)
206 {
207 out_reason = fmt::format("Task {} already executed according to log pointer {}", entry_name, our_log_ptr);
208 return {};
209 }
210
211 String entry_path = fs::path(queue_dir) / entry_name;
212 auto task = std::make_unique<DatabaseReplicatedTask>(entry_name, entry_path, database);
213
214 String initiator_name;
215 zkutil::EventPtr wait_committed_or_failed = std::make_shared<Poco::Event>();
216
217 String try_node_path = fs::path(entry_path) / "try";
218 if (zookeeper->tryGet(try_node_path, initiator_name, nullptr, wait_committed_or_failed))
219 {
220 task->is_initial_query = initiator_name == task->host_id_str;
221
222 /// Query is not committed yet. We cannot just skip it and execute next one, because reordering may break replication.
223 LOG_TRACE(log, "Waiting for initiator {} to commit or rollback entry {}", initiator_name, entry_path);
224 constexpr size_t wait_time_ms = 1000;
225 size_t max_iterations = database->db_settings.wait_entry_commited_timeout_sec;
226 size_t iteration = 0;
227
228 while (!wait_committed_or_failed->tryWait(wait_time_ms))
229 {
230 if (stop_flag)
231 {
232 /// We cannot return task to process and we cannot return nullptr too,
233 /// because nullptr means "task should not be executed".
234 /// We can only exit by exception.
235 throw Exception(ErrorCodes::UNFINISHED, "Replication was stopped");
236 }
237
238 if (max_iterations <= ++iteration)
239 {
240 /// What can we do if initiator hangs for some reason? Seems like we can remove /try node.
241 /// Initiator will fail to commit ZooKeeperMetadataTransaction (including ops for replicated table) if /try does not exist.
242 /// But it's questionable.
243
244 /// We use tryRemove(...) because multiple hosts (including initiator) may try to do it concurrently.
245 auto code = zookeeper->tryRemove(try_node_path);
246 if (code != Coordination::Error::ZOK && code != Coordination::Error::ZNONODE)
247 throw Coordination::Exception(code, try_node_path);
248

Callers

nothing calls this directly

Calls 14

ExecutionStatusClass · 0.85
tryWaitMethod · 0.80
getFinishedNodePathMethod · 0.80
getClusterImplMethod · 0.80
parseQueryFromEntryMethod · 0.80
ExceptionClass · 0.50
getMethod · 0.45
tryGetMethod · 0.45
tryRemoveMethod · 0.45
existsMethod · 0.45
serializeTextMethod · 0.45
parseMethod · 0.45

Tested by

no test coverage detected