mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-14 02:12:21 +00:00
Get rid of metadata references
This commit is contained in:
parent
0d89be20b0
commit
9dc9f67f93
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user