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");
		}
	}
}
Example #2
0
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;
    }
}