| 999 | } |
| 1000 | |
| 1001 | FileSegmentsHolderPtr FileCache::get( |
| 1002 | const Key & key, |
| 1003 | size_t offset, |
| 1004 | size_t size, |
| 1005 | size_t file_segments_limit, |
| 1006 | const UserID & user_id) |
| 1007 | { |
| 1008 | ProfileEventTimeIncrement<Microseconds> watch(ProfileEvents::FilesystemCacheGetMicroseconds); |
| 1009 | |
| 1010 | assertInitialized(); |
| 1011 | |
| 1012 | std::unique_ptr<FileSegmentsHolder> holder; |
| 1013 | if (auto locked_key = metadata.lockKeyMetadata(key, CacheMetadata::KeyNotFoundPolicy::RETURN_NULL, OriginInfo(user_id)); |
| 1014 | locked_key != nullptr) |
| 1015 | { |
| 1016 | FileSegment::Range range(offset, offset + size - 1); |
| 1017 | |
| 1018 | /// Get all segments which intersect with the given range. |
| 1019 | auto file_segments = getImpl(*locked_key, range, file_segments_limit); |
| 1020 | if (!file_segments.empty()) |
| 1021 | { |
| 1022 | if (file_segments_limit) |
| 1023 | { |
| 1024 | chassert(file_segments.size() <= file_segments_limit); |
| 1025 | if (file_segments.size() == file_segments_limit) |
| 1026 | range.right = file_segments.back()->range().right; |
| 1027 | } |
| 1028 | |
| 1029 | fillHolesWithEmptyFileSegments( |
| 1030 | *locked_key, file_segments, range, offset + size - 1, file_segments_limit, /* fill_with_detached */true, CreateFileSegmentSettings{}); |
| 1031 | |
| 1032 | chassert(!file_segments_limit || file_segments.size() <= file_segments_limit); |
| 1033 | holder = std::make_unique<FileSegmentsHolder>(std::move(file_segments)); |
| 1034 | } |
| 1035 | } |
| 1036 | |
| 1037 | if (!holder) |
| 1038 | holder = std::make_unique<FileSegmentsHolder>(FileSegments{std::make_shared<FileSegment>(key, offset, size, FileSegment::State::DETACHED)}); |
| 1039 | |
| 1040 | assertCacheCorrectnessWithProbability(); |
| 1041 | return holder; |
| 1042 | } |
| 1043 | |
| 1044 | FileSegmentsHolderPtr FileCache::getDownloadedContiguousOrEmpty( |
| 1045 | const Key & key, |