void ReplicatedMergeTreeRestartingThread::removeFailedQuorumParts() { auto zookeeper = storage.getZooKeeper(); Strings failed_parts; if (!zookeeper->tryGetChildren(storage.zookeeper_path + "/quorum/failed_parts", failed_parts)) return; for (auto part_name : failed_parts) { auto part = storage.data.getPartIfExists(part_name); if (part) { LOG_DEBUG(log, "Found part " << part_name << " with failed quorum. Moving to detached. This shouldn't happen often."); zkutil::Ops ops; storage.removePartFromZooKeeper(part_name, ops); auto code = zookeeper->tryMulti(ops); if (code == ZNONODE) LOG_WARNING(log, "Part " << part_name << " with failed quorum is not in ZooKeeper. This shouldn't happen often."); storage.data.renameAndDetachPart(part, "noquorum"); } } }
void RWLock::acquireImpl(Mode mode) { static_assert((lock_type == RWLock::Read) || (lock_type == RWLock::Write), "Invalid RWLock type"); __sync_synchronize(); if (!*this) { owns_lock = true; return; } if (!key.empty()) throw DB::Exception{"RWLock: lock already held", DB::ErrorCodes::RWLOCK_ALREADY_HELD}; try { /// Enqueue a new request for a lock. int32_t code = get_zookeeper()->tryCreate(path + "/" + Prefix<lock_type>::name, "", CreateMode::EphemeralSequential, key); if (code == ZNONODE) throw DB::Exception{"No such lock", DB::ErrorCodes::RWLOCK_NO_SUCH_LOCK}; else if (code != ZOK) throw KeeperException(code); key = key.substr(path.length() + 1); while (true) { auto zookeeper = get_zookeeper(); std::vector<std::string> children; int32_t code = zookeeper->tryGetChildren(path, children); if (code == ZNONODE) throw DB::Exception{"No such lock", DB::ErrorCodes::RWLOCK_NO_SUCH_LOCK}; else if (code != ZOK) throw KeeperException{code}; std::sort(children.begin(), children.end(), nodeQueueCmp); auto it = std::lower_bound(children.cbegin(), children.cend(), key, nodeQueueCmp); /// This should never happen. if ((it == children.cend()) || !nodeQueueEquals(*it, key)) throw DB::Exception{"RWLock: corrupted lock request queue. Own request not found.", DB::ErrorCodes::LOGICAL_ERROR}; const std::string * observed_key = nullptr; if (lock_type == RWLock::Read) { /// Look for the first write lock request that is older than us. auto it2 = std::find_if( std::make_reverse_iterator(it), children.crend(), [](const std::string & child) { return startsWith(child, Prefix<RWLock::Write>::name); }); if (it2 != children.crend()) observed_key = &*it2; } else if (lock_type == RWLock::Write) { if (it != children.cbegin()) { /// Take the next lock request that is older than us. auto it2 = std::prev(it); observed_key = &*it2; } } if (observed_key == nullptr) { /// We hold the lock. owns_lock = true; break; } if (mode == NonBlocking) { int32_t code = zookeeper->tryRemoveEphemeralNodeWithRetries(path + "/" + key); if (code == ZNONODE) throw DB::Exception{"No such lock", DB::ErrorCodes::RWLOCK_NO_SUCH_LOCK}; else if (code != ZOK) throw KeeperException{code}; key.clear(); break; } abortIfRequested(); /// Wait for our turn to come. if (zookeeper->exists(path + "/" + *observed_key, nullptr, event)) { do { abortIfRequested(); } while (!event->tryWait(wait_duration)); } } } catch (...) { try { if (!key.empty()) get_zookeeper()->tryRemoveEphemeralNodeWithRetries(path + "/" + key); } catch (...) { DB::tryLogCurrentException(__PRETTY_FUNCTION__); } throw; } }