Get rid of metadata references

This commit is contained in:
kssenii 2023-03-24 17:18:41 +01:00
parent 0d89be20b0
commit 9dc9f67f93
10 changed files with 91 additions and 74 deletions

View File

@ -115,12 +115,12 @@ FileSegments FileCache::getImpl(const LockedKey & locked_key, const FileSegment:
if (bypass_cache_threshold && range.size() > bypass_cache_threshold)
{
auto file_segment = std::make_shared<FileSegment>(
range.left, range.size(), locked_key.getKey(), nullptr, this,
range.left, range.size(), locked_key.getKey(), std::weak_ptr<KeyMetadata>(), this,
FileSegment::State::DETACHED, CreateFileSegmentSettings{});
return { file_segment };
}
const auto & file_segments = locked_key.getKeyMetadata();
const auto & file_segments = *locked_key.getKeyMetadata();
if (file_segments.empty())
return {};
@ -305,7 +305,7 @@ void FileCache::fillHolesWithEmptyFileSegments(
if (fill_with_detached_file_segments)
{
auto file_segment = std::make_shared<FileSegment>(
current_pos, hole_size, locked_key.getKey(), nullptr,
current_pos, hole_size, locked_key.getKey(), std::weak_ptr<KeyMetadata>(),
this, FileSegment::State::DETACHED, settings);
file_segments.insert(it, file_segment);
@ -332,7 +332,7 @@ void FileCache::fillHolesWithEmptyFileSegments(
if (fill_with_detached_file_segments)
{
auto file_segment = std::make_shared<FileSegment>(
current_pos, hole_size, locked_key.getKey(), nullptr , this, FileSegment::State::DETACHED, settings);
current_pos, hole_size, locked_key.getKey(), std::weak_ptr<KeyMetadata>() , this, FileSegment::State::DETACHED, settings);
file_segments.insert(file_segments.end(), file_segment);
}
@ -426,7 +426,7 @@ FileSegmentsHolderPtr FileCache::get(const Key & key, size_t offset, size_t size
}
auto file_segment = std::make_shared<FileSegment>(
offset, size, key, nullptr, this, FileSegment::State::DETACHED, CreateFileSegmentSettings{});
offset, size, key, std::weak_ptr<KeyMetadata>(), this, FileSegment::State::DETACHED, CreateFileSegmentSettings{});
return std::make_unique<FileSegmentsHolder>(FileSegments{file_segment});
}
@ -444,10 +444,10 @@ KeyMetadata::iterator FileCache::addFileSegment(
chassert(size > 0); /// Empty file segments in cache are not allowed.
const auto & key = locked_key.getKey();
auto & key_metadata = locked_key.getKeyMetadata();
auto key_metadata = locked_key.getKeyMetadata();
auto it = key_metadata.find(offset);
if (it != key_metadata.end())
auto it = key_metadata->find(offset);
if (it != key_metadata->end())
{
throw Exception(
ErrorCodes::LOGICAL_ERROR,
@ -491,20 +491,20 @@ KeyMetadata::iterator FileCache::addFileSegment(
result_state = state;
}
auto file_segment = std::make_shared<FileSegment>(offset, size, key, &key_metadata, this, result_state, settings);
auto file_segment = std::make_shared<FileSegment>(offset, size, key, key_metadata, this, result_state, settings);
std::optional<LockedCachePriority> locked_queue(
lock ? LockedCachePriority(*lock, *main_priority) : std::optional<LockedCachePriority>{});
FileSegmentMetadata file_segment_metadata(std::move(file_segment), locked_key, locked_queue ? &*locked_queue : nullptr);
auto [file_segment_metadata_it, inserted] = key_metadata.emplace(offset, std::move(file_segment_metadata));
auto [file_segment_metadata_it, inserted] = key_metadata->emplace(offset, std::move(file_segment_metadata));
assert(inserted);
return file_segment_metadata_it;
}
bool FileCache::tryReserve(const Key & key, size_t offset, size_t size, KeyMetadata & key_metadata)
bool FileCache::tryReserve(const Key & key, size_t offset, size_t size, KeyMetadataPtr key_metadata)
{
assertInitialized();
auto lock = cache_guard.lock();
@ -543,7 +543,7 @@ bool FileCache::tryReserveUnlocked(
if (reserved)
{
auto & key_metadata = locked_key->getKeyMetadata();
auto & key_metadata = *locked_key->getKeyMetadata();
if (!key_metadata.created_base_directory)
{
fs::create_directories(getPathInLocalCache(locked_key->getKey()));
@ -568,7 +568,7 @@ void FileCache::iterateCacheAndCollectKeyLocks(
if (locked)
current = locked_it->second;
else
current = createLockedKey(entry.key, entry.key_metadata);
current = createLockedKey(entry.key, entry.getKeyMetadata());
auto res = func(entry, *current);
if (res.lock_key && !locked)
@ -609,7 +609,7 @@ bool FileCache::tryReserveImpl(
chassert(queue_size <= locked_priority_queue.getElementsLimit());
/// A file_segment_metadata acquires a LRUQueue iterator on first successful space reservation attempt.
auto * file_segment_for_reserve = locked_key->getKeyMetadata().getByOffset(offset);
auto * file_segment_for_reserve = locked_key->getKeyMetadata()->getByOffset(offset);
if (!file_segment_for_reserve->queue_iterator)
queue_size += 1;
@ -638,7 +638,7 @@ bool FileCache::tryReserveImpl(
if (!is_overflow())
return { IterationResult::BREAK, false };
auto * file_segment_metadata = current_locked_key.getKeyMetadata().getByOffset(entry.offset);
auto * file_segment_metadata = current_locked_key.getKeyMetadata()->getByOffset(entry.offset);
chassert(file_segment_metadata->queue_iterator);
chassert(entry.size == file_segment_metadata->size());
@ -700,7 +700,7 @@ bool FileCache::tryReserveImpl(
/// TODO: Add assertion.
for (const auto & offset_to_delete : offsets_to_delete)
{
auto * file_segment_metadata = current_locked_key->getKeyMetadata().getByOffset(offset_to_delete);
auto * file_segment_metadata = current_locked_key->getKeyMetadata()->getByOffset(offset_to_delete);
removeFileSegment(*current_locked_key, file_segment_metadata->file_segment, cache_lock);
if (query_context)
query_context->remove(key, offset);
@ -754,12 +754,12 @@ void FileCache::removeKeyIfExists(const Key & key)
if (!locked_key)
return;
auto & offsets = locked_key->getKeyMetadata();
if (!offsets.empty())
auto & key_metadata = *locked_key->getKeyMetadata();
if (!key_metadata.empty())
{
std::vector<FileSegmentMetadata *> file_segments_metadata_to_remove;
file_segments_metadata_to_remove.reserve(offsets.size());
for (auto & [offset, file_segment_metadata] : offsets)
file_segments_metadata_to_remove.reserve(key_metadata.size());
for (auto & [offset, file_segment_metadata] : key_metadata)
file_segments_metadata_to_remove.push_back(&file_segment_metadata);
for (auto & file_segment_metadata : file_segments_metadata_to_remove)
@ -794,8 +794,8 @@ void FileCache::removeAllReleasable()
auto lock = cache_guard.lock();
LockedCachePriority(lock, *main_priority).iterate([&](const QueueEntry & entry) -> IterationResult
{
auto locked_key = createLockedKey(entry.key, entry.key_metadata);
auto * file_segment_metadata = locked_key->getKeyMetadata().getByOffset(entry.offset);
auto locked_key = createLockedKey(entry.key, entry.getKeyMetadata());
auto * file_segment_metadata = locked_key->getKeyMetadata()->getByOffset(entry.offset);
if (file_segment_metadata->releasable())
{
@ -861,7 +861,7 @@ void FileCache::loadMetadata()
const auto key = Key(unhexUInt<UInt128>(key_it->path().filename().string().data()));
auto locked_key = createLockedKey(key, KeyNotFoundPolicy::CREATE_EMPTY);
locked_key->getKeyMetadata().created_base_directory = true;
locked_key->getKeyMetadata()->created_base_directory = true;
fs::directory_iterator offset_it{key_it->path()};
for (; offset_it != fs::directory_iterator(); ++offset_it)
@ -962,12 +962,6 @@ void FileCache::performDelayedRemovalOfDeletedKeysFromMetadata(const CacheMetada
/// In this case it will work fine because on each attempt to add any key to cache
/// we perform this delayed removal of deleted keys.
/// We need to take this mutex to avoid race with LockedKey destructor.
/// (it submit key to removal queue and then unlocked the mutex,
/// but this mutex lies in metadata which we are going to delete)
auto key_metadata = it->second;
auto lock = key_metadata->lock();
/// Remove key from metadata.
metadata.erase(it);
@ -1027,16 +1021,16 @@ LockedKeyPtr FileCache::createLockedKey(const Key & key, KeyNotFoundPolicy key_n
return nullptr;
it = metadata.emplace(key, std::make_shared<KeyMetadata>()).first;
return std::make_unique<LockedKey>(key, *it->second, it->second->lock(), getPathInLocalCache(key), cleanup_keys_metadata_queue);
return std::make_unique<LockedKey>(key, it->second, it->second->lock(), getPathInLocalCache(key), cleanup_keys_metadata_queue);
}
return std::make_unique<LockedKey>(key, *key_metadata, std::move(key_lock), getPathInLocalCache(key), cleanup_keys_metadata_queue);
return std::make_unique<LockedKey>(key, key_metadata, std::move(key_lock), getPathInLocalCache(key), cleanup_keys_metadata_queue);
}
LockedKeyPtr FileCache::createLockedKey(const Key & key, KeyMetadata & key_metadata) const
LockedKeyPtr FileCache::createLockedKey(const Key & key, KeyMetadataPtr key_metadata) const
{
auto key_lock = key_metadata.lock();
if (key_metadata.removed)
auto key_lock = key_metadata->lock();
if (key_metadata->removed)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot lock key: it was removed from cache");
return std::make_unique<LockedKey>(key, key_metadata, std::move(key_lock), getPathInLocalCache(key), cleanup_keys_metadata_queue);
}
@ -1085,7 +1079,7 @@ FileSegmentsHolderPtr FileCache::getSnapshot(const Key & key)
{
FileSegments file_segments;
auto locked_key = createLockedKey(key, KeyNotFoundPolicy::THROW);
for (const auto & [_, file_segment_metadata] : locked_key->getKeyMetadata())
for (const auto & [_, file_segment_metadata] : *locked_key->getKeyMetadata())
file_segments.push_back(FileSegment::getSnapshot(file_segment_metadata.file_segment));
return std::make_unique<FileSegmentsHolder>(std::move(file_segments));
}
@ -1099,8 +1093,8 @@ FileSegmentsHolderPtr FileCache::dumpQueue()
FileSegments file_segments;
LockedCachePriority(cache_guard.lock(), *main_priority).iterate([&](const QueueEntry & entry)
{
auto tx = createLockedKey(entry.key, entry.key_metadata);
auto * file_segment_metadata = tx->getKeyMetadata().getByOffset(entry.offset);
auto tx = createLockedKey(entry.key, entry.getKeyMetadata());
auto * file_segment_metadata = tx->getKeyMetadata()->getByOffset(entry.offset);
file_segments.push_back(FileSegment::getSnapshot(file_segment_metadata->file_segment));
return IterationResult::CONTINUE;
});
@ -1118,7 +1112,7 @@ std::vector<String> FileCache::tryGetCachePaths(const Key & key)
std::vector<String> cache_paths;
for (const auto & [offset, file_segment_metadata] : locked_key->getKeyMetadata())
for (const auto & [offset, file_segment_metadata] : *locked_key->getKeyMetadata())
{
if (file_segment_metadata.file_segment->state() == FileSegment::State::DOWNLOADED)
cache_paths.push_back(getPathInLocalCache(key, offset, file_segment_metadata.file_segment->getKind()));
@ -1162,8 +1156,8 @@ void FileCache::assertCacheCorrectness(
queue.iterate([&](const QueueEntry & entry) -> IterationResult
{
auto locked_key = createLockedKey(entry.key, entry.key_metadata);
auto * file_segment_metadata = locked_key->getKeyMetadata().getByOffset(entry.offset);
auto locked_key = createLockedKey(entry.key, entry.getKeyMetadata());
auto * file_segment_metadata = locked_key->getKeyMetadata()->getByOffset(entry.offset);
if (file_segment_metadata->size() != entry.size)
{

View File

@ -98,7 +98,7 @@ public:
size_t getMaxFileSegmentSize() const { return max_file_segment_size; }
bool tryReserve(const Key & key, size_t offset, size_t size, KeyMetadata & key_metadata);
bool tryReserve(const Key & key, size_t offset, size_t size, KeyMetadataPtr key_metadata);
FileSegmentsHolderPtr getSnapshot();
@ -110,7 +110,7 @@ public:
CacheGuard::Lock cacheLock() { return cache_guard.lock(); }
LockedKeyPtr createLockedKey(const Key & key, KeyMetadata & key_metadata) const;
LockedKeyPtr createLockedKey(const Key & key, KeyMetadataPtr key_metadata) const;
/// For per query cache limit.
struct QueryContextHolder : private boost::noncopyable

View File

@ -28,13 +28,13 @@ FileSegment::FileSegment(
size_t offset_,
size_t size_,
const Key & key_,
KeyMetadata * key_metadata_,
std::weak_ptr<KeyMetadata> key_metadata_,
FileCache * cache_,
State download_state_,
const CreateFileSegmentSettings & settings)
: segment_range(offset_, offset_ + size_ - 1)
, download_state(download_state_)
, key_metadata(std::move(key_metadata_))
, key_metadata(key_metadata_)
, file_key(key_)
, file_path(cache_->getPathInLocalCache(key(), offset(), settings.kind))
, cache(cache_)
@ -379,15 +379,21 @@ FileSegment::State FileSegment::wait()
return download_state;
}
LockedKeyPtr FileSegment::createLockedKey(bool assert_exists) const
KeyMetadataPtr FileSegment::getKeyMetadata(bool assert_exists) const
{
if (!key_metadata)
auto metadata = key_metadata.lock();
if (!metadata)
{
if (assert_exists)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot lock key, key metadata is not set");
return nullptr;
}
return cache->createLockedKey(key(), *key_metadata);
return metadata;
}
LockedKeyPtr FileSegment::createLockedKey(bool assert_exists) const
{
return cache->createLockedKey(key(), getKeyMetadata(assert_exists));
}
bool FileSegment::reserve(size_t size_to_reserve)
@ -438,7 +444,7 @@ bool FileSegment::reserve(size_t size_to_reserve)
if (is_unbound && is_file_segment_size_exceeded)
segment_range.right = range().left + expected_downloaded_size + size_to_reserve;
reserved = cache->tryReserve(key(), offset(), size_to_reserve, *key_metadata);
reserved = cache->tryReserve(key(), offset(), size_to_reserve, getKeyMetadata(true));
if (reserved)
{
/// No lock is required because reserved size is always
@ -711,7 +717,7 @@ FileSegmentPtr FileSegment::getSnapshot(const FileSegmentPtr & file_segment)
file_segment->offset(),
file_segment->range().size(),
file_segment->key(),
nullptr,
std::weak_ptr<KeyMetadata>(),
file_segment->cache,
State::DETACHED,
CreateFileSegmentSettings(file_segment->getKind()));
@ -737,9 +743,9 @@ bool FileSegment::isCompleted(bool sync) const
{
return download_state == State::DOWNLOADED
|| download_state == State::DETACHED
/// the following means that file segment was shrinked to the downloaded size via calling complete().
/// the following means that file segment was shrunk to the downloaded size via calling complete().
/// a more correct way to call such state is PARTIALLY_DOWNLOADED_NO_CONTINUATION_DETACHED.
|| ((download_state == State::PARTIALLY_DOWNLOADED_NO_CONTINUATION) && (key_metadata == nullptr));
|| ((download_state == State::PARTIALLY_DOWNLOADED_NO_CONTINUATION) && (key_metadata.expired()));
};
if (sync)
@ -764,7 +770,7 @@ void FileSegment::detach(const FileSegmentGuard::Lock & lock, const LockedKey &)
void FileSegment::detachAssumeStateFinalized(const FileSegmentGuard::Lock & lock)
{
key_metadata = nullptr;
key_metadata.reset();
LOG_TEST(log, "Detached file segment: {}", getInfoForLogUnlocked(lock));
}
@ -783,7 +789,7 @@ FileSegments::iterator FileSegmentsHolder::completeAndPopFrontImpl()
auto locked_key = file_segment.createLockedKey(/* assert_exists */false);
if (locked_key)
{
auto queue_iter = locked_key->getKeyMetadata().tryGetByOffset(file_segment.offset())->queue_iterator;
auto queue_iter = locked_key->getKeyMetadata()->tryGetByOffset(file_segment.offset())->queue_iterator;
if (queue_iter)
LockedCachePriorityIterator(cache_lock, queue_iter).use();

View File

@ -33,6 +33,7 @@ using FileSegments = std::list<FileSegmentPtr>;
struct LockedKey;
using LockedKeyPtr = std::shared_ptr<LockedKey>;
struct KeyMetadata;
using KeyMetadataPtr = std::shared_ptr<KeyMetadata>;
/*
* FileSegmentKind is used to specify the eviction policy for file segments.
@ -122,7 +123,7 @@ public:
size_t offset_,
size_t size_,
const Key & key_,
KeyMetadata * key_metadata,
std::weak_ptr<KeyMetadata> key_metadata,
FileCache * cache_,
State download_state_,
const CreateFileSegmentSettings & create_settings);
@ -284,6 +285,7 @@ private:
void assertCorrectnessUnlocked(const FileSegmentGuard::Lock &) const;
LockedKeyPtr createLockedKey(bool assert_exists = true) const;
KeyMetadataPtr getKeyMetadata(bool assert_exists) const;
/// completeWithoutStateUnlocked() is called from destructor of FileSegmentsHolder.
/// Function might check if the caller of the method
@ -312,7 +314,7 @@ private:
mutable std::mutex download_mutex;
mutable FileSegmentGuard segment_guard;
KeyMetadata * key_metadata;
std::weak_ptr<KeyMetadata> key_metadata;
std::condition_variable cv;
Key file_key;

View File

@ -15,6 +15,11 @@ using FileCachePriorityPtr = std::unique_ptr<IFileCachePriority>;
struct KeyMetadata;
using KeyMetadataPtr = std::shared_ptr<KeyMetadata>;
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
}
/// IFileCachePriority is used to maintain the priority of cached data.
class IFileCachePriority
{
@ -25,14 +30,25 @@ public:
struct Entry
{
Entry(const Key & key_, size_t offset_, size_t size_, KeyMetadata & key_metadata_)
Entry(const Key & key_, size_t offset_, size_t size_, std::weak_ptr<KeyMetadata> key_metadata_)
: key(key_) , offset(offset_) , size(size_) , key_metadata(key_metadata_) {}
KeyMetadataPtr getKeyMetadata() const
{
auto result = key_metadata.lock();
if (!result)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Metadata expired");
return result;
}
Key key;
size_t offset;
size_t size;
size_t hits = 0;
KeyMetadata & key_metadata;
/// In fact, it is guaranteed that the lifetime of key metadata is longer
/// than Entry, but it is made as weak_ptr to avoid cycle in shared pointer
/// references (because entry actually lies in key metadata).
const std::weak_ptr<KeyMetadata> key_metadata;
};
/// Provides an iterator to traverse the cache priority. Under normal circumstances,
@ -83,7 +99,7 @@ protected:
virtual size_t getElementsCount() const = 0;
virtual Iterator add(const Key & key, size_t offset, size_t size, KeyMetadata & key_metadata) = 0;
virtual Iterator add(const Key & key, size_t offset, size_t size, std::weak_ptr<KeyMetadata> key_metadata) = 0;
virtual void pop() = 0;

View File

@ -17,7 +17,7 @@ namespace ErrorCodes
}
IFileCachePriority::Iterator LRUFileCachePriority::add(
const Key & key, size_t offset, size_t size, KeyMetadata & key_metadata)
const Key & key, size_t offset, size_t size, std::weak_ptr<KeyMetadata> key_metadata)
{
#ifndef NDEBUG
for (const auto & entry : queue)

View File

@ -24,7 +24,7 @@ public:
size_t getElementsCount() const override { return queue.size(); }
Iterator add(const Key & key, size_t offset, size_t size, KeyMetadata & key_metadata) override;
Iterator add(const Key & key, size_t offset, size_t size, std::weak_ptr<KeyMetadata> key_metadata) override;
void pop() override;

View File

@ -19,7 +19,7 @@ public:
size_t getElementsCount() const { return queue.getElementsCount(); }
IFileCachePriority::Iterator add(const FileCacheKey & key, size_t offset, size_t size, KeyMetadata & key_metadata)
IFileCachePriority::Iterator add(const FileCacheKey & key, size_t offset, size_t size, std::weak_ptr<KeyMetadata> key_metadata)
{
return queue.add(key, offset, size, key_metadata);
}

View File

@ -16,7 +16,7 @@ namespace ErrorCodes
LockedKey::LockedKey(
const FileCacheKey & key_,
KeyMetadata & key_metadata_,
std::shared_ptr<KeyMetadata> key_metadata_,
KeyGuard::Lock && lock_,
const std::string & key_path_,
KeysQueuePtr cleanup_keys_metadata_queue_)
@ -36,7 +36,7 @@ LockedKey::~LockedKey()
bool LockedKey::isLastOwnerOfFileSegment(size_t offset) const
{
const auto * file_segment_metadata = key_metadata.getByOffset(offset);
const auto * file_segment_metadata = key_metadata->getByOffset(offset);
return file_segment_metadata->file_segment.use_count() == 2;
}
@ -49,7 +49,7 @@ void LockedKey::removeFileSegment(
log, "Remove from cache. Key: {}, offset: {}",
key.toString(), offset);
auto * file_segment_metadata = key_metadata.getByOffset(offset);
auto * file_segment_metadata = key_metadata->getByOffset(offset);
if (file_segment_metadata->queue_iterator)
LockedCachePriorityIterator(cache_lock, file_segment_metadata->queue_iterator).remove();
@ -57,7 +57,7 @@ void LockedKey::removeFileSegment(
const auto cache_file_path = file_segment_metadata->file_segment->getPathInLocalCache();
file_segment_metadata->file_segment->detach(segment_lock, *this);
key_metadata.erase(offset);
key_metadata->erase(offset);
if (fs::exists(cache_file_path))
fs::remove(cache_file_path);
@ -73,7 +73,7 @@ void LockedKey::shrinkFileSegmentToDownloadedSize(
* because of no space left in cache, we need to be able to cut file segment's size to downloaded_size.
*/
auto * file_segment_metadata = key_metadata.getByOffset(offset);
auto * file_segment_metadata = key_metadata->getByOffset(offset);
const auto & file_segment = file_segment_metadata->file_segment;
size_t downloaded_size = file_segment->downloaded_size;
@ -94,7 +94,7 @@ void LockedKey::shrinkFileSegmentToDownloadedSize(
CreateFileSegmentSettings create_settings(file_segment->getKind());
file_segment_metadata->file_segment = std::make_shared<FileSegment>(
offset, downloaded_size, key, &key_metadata, file_segment->cache, FileSegment::State::DOWNLOADED, create_settings);
offset, downloaded_size, key, key_metadata, file_segment->cache, FileSegment::State::DOWNLOADED, create_settings);
if (file_segment->reserved_size > file_segment->downloaded_size)
entry.size = downloaded_size;
@ -106,16 +106,16 @@ void LockedKey::shrinkFileSegmentToDownloadedSize(
void LockedKey::removeKeyIfEmpty() const
{
/// Someone might still need this directory.
if (!key_metadata.empty())
if (!key_metadata->empty())
return;
key_metadata.removed = true;
key_metadata->removed = true;
/// Now `key_metadata` empty and the key lock is still locked.
/// So it is guaranteed that no one will add something.
if (fs::exists(key_path))
{
key_metadata.created_base_directory = false;
key_metadata->created_base_directory = false;
fs::remove_all(key_path);
}
cleanup_keys_metadata_queue->add(key);

View File

@ -29,7 +29,7 @@ struct LockedKey : private boost::noncopyable
{
LockedKey(
const FileCacheKey & key_,
KeyMetadata & key_metadata_,
std::shared_ptr<KeyMetadata> key_metadata_,
KeyGuard::Lock && key_lock_,
const std::string & key_path_,
KeysQueuePtr cleanup_keys_metadata_queue_);
@ -38,8 +38,7 @@ struct LockedKey : private boost::noncopyable
const FileCacheKey & getKey() const { return key; }
const KeyMetadata & getKeyMetadata() const { return key_metadata; }
KeyMetadata & getKeyMetadata() { return key_metadata; }
KeyMetadataPtr getKeyMetadata() const { return key_metadata; }
void removeFileSegment(size_t offset, const FileSegmentGuard::Lock &, const CacheGuard::Lock &);
@ -54,7 +53,7 @@ private:
const std::string key_path;
KeyGuard::Lock lock;
KeyMetadata & key_metadata;
const std::shared_ptr<KeyMetadata> key_metadata;
KeysQueuePtr cleanup_keys_metadata_queue;
Poco::Logger * log;