Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lock categories to control different lock-purposes #12163

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 53 additions & 13 deletions ydb/core/tx/columnshard/data_locks/locks/abstract.h
Original file line number Diff line number Diff line change
@@ -1,53 +1,93 @@
#pragma once
#include <ydb/library/accessor/accessor.h>

#include <util/generic/string.h>
#include <util/generic/hash_set.h>
#include <util/generic/string.h>

#include <optional>
#include <memory>
#include <optional>
#include <set>
#include <vector>

namespace NKikimr::NOlap {
class TPortionInfo;
class TGranuleMeta;
}
} // namespace NKikimr::NOlap

namespace NKikimr::NOlap::NDataLocks {

enum class ELockCategory : ui32 {
Compaction = 0,
Cleanup,
Sharing,
Actualization,
Tables,
Any,
MAX
};

static const inline std::array<std::set<ELockCategory>, (ui32)ELockCategory::MAX> LockCategoriesInteraction = {
//Compaction
std::set<ELockCategory>({ ELockCategory::Compaction, ELockCategory::Actualization, ELockCategory::Tables, ELockCategory::Any}),
//Cleanup
std::set<ELockCategory>({ ELockCategory::Cleanup, ELockCategory::Sharing, ELockCategory::Tables, ELockCategory::Any }),
//Sharing
std::set<ELockCategory>({ ELockCategory::Sharing, ELockCategory::Cleanup, ELockCategory::Tables, ELockCategory::Any }),
//Actualization
std::set<ELockCategory>({ ELockCategory::Actualization, ELockCategory::Compaction, ELockCategory::Tables, ELockCategory::Any }),
//Tables
std::set<ELockCategory>({ ELockCategory::Cleanup, ELockCategory::Sharing, ELockCategory::Actualization, ELockCategory::Compaction,
ELockCategory::Tables, ELockCategory::Any }),
//Any
std::set<ELockCategory>({ ELockCategory::Cleanup, ELockCategory::Sharing, ELockCategory::Actualization, ELockCategory::Compaction,
ELockCategory::Tables, ELockCategory::Any }),
};

class ILock {
private:
YDB_READONLY_DEF(TString, LockName);
YDB_READONLY_FLAG(ReadOnly, false);
const ELockCategory Category;

protected:
virtual std::optional<TString> DoIsLocked(const TPortionInfo& portion, const THashSet<TString>& excludedLocks = {}) const = 0;
virtual std::optional<TString> DoIsLocked(const TGranuleMeta& granule, const THashSet<TString>& excludedLocks = {}) const = 0;
virtual std::optional<TString> DoIsLocked(
const TPortionInfo& portion, const ELockCategory category, const THashSet<TString>& excludedLocks = {}) const = 0;
virtual std::optional<TString> DoIsLocked(
const TGranuleMeta& granule, const ELockCategory category, const THashSet<TString>& excludedLocks = {}) const = 0;
virtual bool DoIsEmpty() const = 0;

public:
ILock(const TString& lockName, const bool isReadOnly = false)
ILock(const TString& lockName, const ELockCategory category, const bool isReadOnly = false)
: LockName(lockName)
, ReadOnlyFlag(isReadOnly)
{

, Category(category) {
}

virtual ~ILock() = default;

std::optional<TString> IsLocked(const TPortionInfo& portion, const THashSet<TString>& excludedLocks = {}, const bool readOnly = false) const {
std::optional<TString> IsLocked(const TPortionInfo& portion, const ELockCategory portionForLock, const THashSet<TString>& excludedLocks = {},
const bool readOnly = false) const {
if (IsReadOnly() && readOnly) {
return {};
}
return DoIsLocked(portion, excludedLocks);
if (!LockCategoriesInteraction[(ui32)Category].contains(portionForLock)) {
return {};
}
return DoIsLocked(portion, portionForLock, excludedLocks);
}
std::optional<TString> IsLocked(const TGranuleMeta& g, const THashSet<TString>& excludedLocks = {}, const bool readOnly = false) const {
std::optional<TString> IsLocked(const TGranuleMeta& g, const ELockCategory portionForLock, const THashSet<TString>& excludedLocks = {},
const bool readOnly = false) const {
if (IsReadOnly() && readOnly) {
return {};
}
return DoIsLocked(g, excludedLocks);
if (!LockCategoriesInteraction[(ui32)Category].contains(portionForLock)) {
return {};
}
return DoIsLocked(g, portionForLock, excludedLocks);
}
bool IsEmpty() const {
return DoIsEmpty();
}
};

}
} // namespace NKikimr::NOlap::NDataLocks
19 changes: 11 additions & 8 deletions ydb/core/tx/columnshard/data_locks/locks/composite.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,24 @@ class TCompositeLock: public ILock {
using TBase = ILock;
std::vector<std::shared_ptr<ILock>> Locks;
protected:
virtual std::optional<TString> DoIsLocked(const TPortionInfo& portion, const THashSet<TString>& excludedLocks) const override {
virtual std::optional<TString> DoIsLocked(const TPortionInfo& portion, const ELockCategory category, const THashSet<TString>& excludedLocks) const override {
for (auto&& i : Locks) {
if (excludedLocks.contains(i->GetLockName())) {
continue;
}
if (auto lockName = i->IsLocked(portion)) {
if (auto lockName = i->IsLocked(portion, category)) {
return lockName;
}
}
return {};
}
virtual std::optional<TString> DoIsLocked(const TGranuleMeta& granule, const THashSet<TString>& excludedLocks) const override {
virtual std::optional<TString> DoIsLocked(
const TGranuleMeta& granule, const ELockCategory category, const THashSet<TString>& excludedLocks) const override {
for (auto&& i : Locks) {
if (excludedLocks.contains(i->GetLockName())) {
continue;
}
if (auto lockName = i->IsLocked(granule)) {
if (auto lockName = i->IsLocked(granule, category)) {
return lockName;
}
}
Expand All @@ -34,8 +35,9 @@ class TCompositeLock: public ILock {
return Locks.empty();
}
public:
TCompositeLock(const TString& lockName, const std::vector<std::shared_ptr<ILock>>& locks, const bool readOnly = false)
: TBase(lockName, readOnly)
TCompositeLock(const TString& lockName, const std::vector<std::shared_ptr<ILock>>& locks,
const ELockCategory category = NDataLocks::ELockCategory::Any, const bool readOnly = false)
: TBase(lockName, category, readOnly)
{
for (auto&& l : locks) {
if (!l || l->IsEmpty()) {
Expand All @@ -45,8 +47,9 @@ class TCompositeLock: public ILock {
}
}

TCompositeLock(const TString& lockName, std::initializer_list<std::shared_ptr<ILock>> locks, const bool readOnly = false)
: TBase(lockName, readOnly)
TCompositeLock(const TString& lockName, std::initializer_list<std::shared_ptr<ILock>> locks,
const ELockCategory category = NDataLocks::ELockCategory::Any, const bool readOnly = false)
: TBase(lockName, category, readOnly)
{
for (auto&& l : locks) {
if (!l || l->IsEmpty()) {
Expand Down
50 changes: 30 additions & 20 deletions ydb/core/tx/columnshard/data_locks/locks/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ class TListPortionsLock: public ILock {
THashSet<TPortionAddress> Portions;
THashSet<ui64> Granules;
protected:
virtual std::optional<TString> DoIsLocked(const TPortionInfo& portion, const THashSet<TString>& /*excludedLocks*/) const override {
virtual std::optional<TString> DoIsLocked(
const TPortionInfo& portion, const ELockCategory /*category*/, const THashSet<TString>& /*excludedLocks*/) const override {
if (Portions.contains(portion.GetAddress())) {
return GetLockName();
}
return {};
}
virtual std::optional<TString> DoIsLocked(const TGranuleMeta& granule, const THashSet<TString>& /*excludedLocks*/) const override {
virtual std::optional<TString> DoIsLocked(
const TGranuleMeta& granule, const ELockCategory /*category*/, const THashSet<TString>& /*excludedLocks*/) const override {
if (Granules.contains(granule.GetPathId())) {
return GetLockName();
}
Expand All @@ -27,42 +29,46 @@ class TListPortionsLock: public ILock {
return Portions.empty();
}
public:
TListPortionsLock(const TString& lockName, const std::vector<TPortionDataAccessor>& portions, const bool readOnly = false)
: TBase(lockName, readOnly)
TListPortionsLock(const TString& lockName, const std::vector<TPortionDataAccessor>& portions, const ELockCategory category, const bool readOnly = false)
: TBase(lockName, category, readOnly)
{
for (auto&& p : portions) {
Portions.emplace(p.GetPortionInfo().GetAddress());
Granules.emplace(p.GetPortionInfo().GetPathId());
}
}

TListPortionsLock(const TString& lockName, const std::vector<std::shared_ptr<TPortionInfo>>& portions, const bool readOnly = false)
: TBase(lockName, readOnly) {
TListPortionsLock(const TString& lockName, const std::vector<std::shared_ptr<TPortionInfo>>& portions, const ELockCategory category,
const bool readOnly = false)
: TBase(lockName, category, readOnly) {
for (auto&& p : portions) {
Portions.emplace(p->GetAddress());
Granules.emplace(p->GetPathId());
}
}

TListPortionsLock(const TString& lockName, const std::vector<TPortionInfo::TConstPtr>& portions, const bool readOnly = false)
: TBase(lockName, readOnly) {
TListPortionsLock(
const TString& lockName, const std::vector<TPortionInfo::TConstPtr>& portions, const ELockCategory category, const bool readOnly = false)
: TBase(lockName, category, readOnly) {
for (auto&& p : portions) {
Portions.emplace(p->GetAddress());
Granules.emplace(p->GetPathId());
}
}

TListPortionsLock(const TString& lockName, const std::vector<TPortionInfo>& portions, const bool readOnly = false)
: TBase(lockName, readOnly) {
TListPortionsLock(
const TString& lockName, const std::vector<TPortionInfo>& portions, const ELockCategory category, const bool readOnly = false)
: TBase(lockName, category, readOnly) {
for (auto&& p : portions) {
Portions.emplace(p.GetAddress());
Granules.emplace(p.GetPathId());
}
}

template <class T, class TGetter>
TListPortionsLock(const TString& lockName, const std::vector<T>& portions, const TGetter& g, const bool readOnly = false)
: TBase(lockName, readOnly) {
TListPortionsLock(
const TString& lockName, const std::vector<T>& portions, const TGetter& g, const ELockCategory category, const bool readOnly = false)
: TBase(lockName, category, readOnly) {
for (auto&& p : portions) {
const auto address = g(p);
Portions.emplace(address);
Expand All @@ -71,17 +77,19 @@ class TListPortionsLock: public ILock {
}

template <class T>
TListPortionsLock(const TString& lockName, const THashMap<TPortionAddress, T>& portions, const bool readOnly = false)
: TBase(lockName, readOnly) {
TListPortionsLock(
const TString& lockName, const THashMap<TPortionAddress, T>& portions, const ELockCategory category, const bool readOnly = false)
: TBase(lockName, category, readOnly) {
for (auto&& p : portions) {
const auto address = p.first;
Portions.emplace(address);
Granules.emplace(address.GetPathId());
}
}

TListPortionsLock(const TString& lockName, const THashSet<TPortionAddress>& portions, const bool readOnly = false)
: TBase(lockName, readOnly) {
TListPortionsLock(
const TString& lockName, const THashSet<TPortionAddress>& portions, const ELockCategory category, const bool readOnly = false)
: TBase(lockName, category, readOnly) {
for (auto&& address : portions) {
Portions.emplace(address);
Granules.emplace(address.GetPathId());
Expand All @@ -94,13 +102,15 @@ class TListTablesLock: public ILock {
using TBase = ILock;
THashSet<ui64> Tables;
protected:
virtual std::optional<TString> DoIsLocked(const TPortionInfo& portion, const THashSet<TString>& /*excludedLocks*/) const override {
virtual std::optional<TString> DoIsLocked(
const TPortionInfo& portion, const ELockCategory /*category*/, const THashSet<TString>& /*excludedLocks*/) const override {
if (Tables.contains(portion.GetPathId())) {
return GetLockName();
}
return {};
}
virtual std::optional<TString> DoIsLocked(const TGranuleMeta& granule, const THashSet<TString>& /*excludedLocks*/) const override {
virtual std::optional<TString> DoIsLocked(
const TGranuleMeta& granule, const ELockCategory /*category*/, const THashSet<TString>& /*excludedLocks*/) const override {
if (Tables.contains(granule.GetPathId())) {
return GetLockName();
}
Expand All @@ -110,8 +120,8 @@ class TListTablesLock: public ILock {
return Tables.empty();
}
public:
TListTablesLock(const TString& lockName, const THashSet<ui64>& tables, const bool readOnly = false)
: TBase(lockName, readOnly)
TListTablesLock(const TString& lockName, const THashSet<ui64>& tables, const ELockCategory category, const bool readOnly = false)
: TBase(lockName, category, readOnly)
, Tables(tables)
{
}
Expand Down
10 changes: 6 additions & 4 deletions ydb/core/tx/columnshard/data_locks/locks/snapshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class TSnapshotLock: public ILock {
const TSnapshot SnapshotBarrier;
const THashSet<ui64> PathIds;
protected:
virtual std::optional<TString> DoIsLocked(const TPortionInfo& portion, const THashSet<TString>& /*excludedLocks*/) const override {
virtual std::optional<TString> DoIsLocked(
const TPortionInfo& portion, const ELockCategory /*category*/, const THashSet<TString>& /*excludedLocks*/) const override {
if (PathIds.contains(portion.GetPathId()) && portion.RecordSnapshotMin() <= SnapshotBarrier) {
return GetLockName();
}
Expand All @@ -20,15 +21,16 @@ class TSnapshotLock: public ILock {
virtual bool DoIsEmpty() const override {
return PathIds.empty();
}
virtual std::optional<TString> DoIsLocked(const TGranuleMeta& granule, const THashSet<TString>& /*excludedLocks*/) const override {
virtual std::optional<TString> DoIsLocked(
const TGranuleMeta& granule, const ELockCategory /*category*/, const THashSet<TString>& /*excludedLocks*/) const override {
if (PathIds.contains(granule.GetPathId())) {
return GetLockName();
}
return {};
}
public:
TSnapshotLock(const TString& lockName, const TSnapshot& snapshotBarrier, const THashSet<ui64>& pathIds, const bool readOnly = false)
: TBase(lockName, readOnly)
TSnapshotLock(const TString& lockName, const TSnapshot& snapshotBarrier, const THashSet<ui64>& pathIds, const ELockCategory category, const bool readOnly = false)
: TBase(lockName, category, readOnly)
, SnapshotBarrier(snapshotBarrier)
, PathIds(pathIds)
{
Expand Down
16 changes: 9 additions & 7 deletions ydb/core/tx/columnshard/data_locks/manager/manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,36 @@ void TManager::UnregisterLock(const TString& processId) {
AFL_VERIFY(ProcessLocks.erase(processId))("process_id", processId);
}

std::optional<TString> TManager::IsLocked(const TPortionInfo& portion, const THashSet<TString>& excludedLocks) const {
std::optional<TString> TManager::IsLocked(
const TPortionInfo& portion, const ELockCategory lockCategory, const THashSet<TString>& excludedLocks) const {
for (auto&& i : ProcessLocks) {
if (excludedLocks.contains(i.first)) {
continue;
}
if (auto lockName = i.second->IsLocked(portion, excludedLocks)) {
if (auto lockName = i.second->IsLocked(portion, lockCategory, excludedLocks)) {
return lockName;
}
}
return {};
}

std::optional<TString> TManager::IsLocked(const TGranuleMeta& granule, const THashSet<TString>& excludedLocks) const {
std::optional<TString> TManager::IsLocked(
const TGranuleMeta& granule, const ELockCategory lockCategory, const THashSet<TString>& excludedLocks) const {
for (auto&& i : ProcessLocks) {
if (excludedLocks.contains(i.first)) {
continue;
}
if (auto lockName = i.second->IsLocked(granule, excludedLocks)) {
if (auto lockName = i.second->IsLocked(granule, lockCategory, excludedLocks)) {
return lockName;
}
}
return {};
}

std::optional<TString> TManager::IsLocked(
const std::shared_ptr<const TPortionInfo>& portion, const THashSet<TString>& excludedLocks /*= {}*/) const {
std::optional<TString> TManager::IsLocked(const std::shared_ptr<const TPortionInfo>& portion, const ELockCategory lockCategory,
const THashSet<TString>& excludedLocks /*= {}*/) const {
AFL_VERIFY(!!portion);
return IsLocked(*portion, excludedLocks);
return IsLocked(*portion, lockCategory, excludedLocks);
}

void TManager::Stop() {
Expand Down
9 changes: 6 additions & 3 deletions ydb/core/tx/columnshard/data_locks/manager/manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ class TManager {
[[nodiscard]] std::shared_ptr<TGuard> RegisterLock(Args&&... args) {
return RegisterLock(std::make_shared<TLock>(args...));
}
std::optional<TString> IsLocked(const TPortionInfo& portion, const THashSet<TString>& excludedLocks = {}) const;
std::optional<TString> IsLocked(const std::shared_ptr<const TPortionInfo>& portion, const THashSet<TString>& excludedLocks = {}) const;
std::optional<TString> IsLocked(const TGranuleMeta& granule, const THashSet<TString>& excludedLocks = {}) const;
std::optional<TString> IsLocked(
const TPortionInfo& portion, const ELockCategory lockCategory, const THashSet<TString>& excludedLocks = {}) const;
std::optional<TString> IsLocked(
const std::shared_ptr<const TPortionInfo>& portion, const ELockCategory lockCategory, const THashSet<TString>& excludedLocks = {}) const;
std::optional<TString> IsLocked(
const TGranuleMeta& granule, const ELockCategory lockCategory, const THashSet<TString>& excludedLocks = {}) const;

};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ TConclusionStatus TCommonSession::TryStart(NColumnShard::TColumnShard& shard) {
for (auto&& i : GetPathIdsForStart()) {
const auto& g = index.GetGranuleVerified(i);
for (auto&& p : g.GetPortionsOlderThenSnapshot(GetSnapshotBarrier())) {
if (shard.GetDataLocksManager()->IsLocked(*p.second, { "sharing_session:" + GetSessionId() })) {
if (shard.GetDataLocksManager()->IsLocked(
*p.second, NDataLocks::ELockCategory::Sharing, { "sharing_session:" + GetSessionId() })) {
return TConclusionStatus::Fail("failed to start cursor: portion is locked");
}
// portionsByPath[i].emplace_back(p.second);
Expand All @@ -48,7 +49,7 @@ void TCommonSession::PrepareToStart(const NColumnShard::TColumnShard& shard) {
State = EState::Prepared;
AFL_VERIFY(!LockGuard);
LockGuard = shard.GetDataLocksManager()->RegisterLock<NDataLocks::TSnapshotLock>("sharing_session:" + GetSessionId(),
TransferContext.GetSnapshotBarrierVerified(), GetPathIdsForStart(), true);
TransferContext.GetSnapshotBarrierVerified(), GetPathIdsForStart(), NDataLocks::ELockCategory::Sharing, true);
shard.GetSharingSessionsManager()->StartSharingSession();
}

Expand Down
Loading
Loading