]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/table/block_based/block_based_table_reader_impl.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / table / block_based / block_based_table_reader_impl.h
CommitLineData
20effc67
TL
1// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2// This source code is licensed under both the GPLv2 (found in the
3// COPYING file in the root directory) and Apache 2.0 License
4// (found in the LICENSE.Apache file in the root directory).
5//
6// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7// Use of this source code is governed by a BSD-style license that can be
8// found in the LICENSE file. See the AUTHORS file for names of contributors.
9#pragma once
10#include "table/block_based/block_based_table_reader.h"
20effc67
TL
11#include "table/block_based/reader_common.h"
12
13// The file contains some member functions of BlockBasedTable that
14// cannot be implemented in block_based_table_reader.cc because
15// it's called by other files (e.g. block_based_iterator.h) and
16// are templates.
17
18namespace ROCKSDB_NAMESPACE {
19// Convert an index iterator value (i.e., an encoded BlockHandle)
20// into an iterator over the contents of the corresponding block.
21// If input_iter is null, new a iterator
22// If input_iter is not null, update this iter and return it
23template <typename TBlockIter>
24TBlockIter* BlockBasedTable::NewDataBlockIterator(
25 const ReadOptions& ro, const BlockHandle& handle, TBlockIter* input_iter,
26 BlockType block_type, GetContext* get_context,
1e59de90
TL
27 BlockCacheLookupContext* lookup_context,
28 FilePrefetchBuffer* prefetch_buffer, bool for_compaction, bool async_read,
29 Status& s) const {
20effc67
TL
30 PERF_TIMER_GUARD(new_table_block_iter_nanos);
31
32 TBlockIter* iter = input_iter != nullptr ? input_iter : new TBlockIter;
33 if (!s.ok()) {
34 iter->Invalidate(s);
35 return iter;
36 }
37
1e59de90
TL
38 CachableEntry<Block> block;
39 if (rep_->uncompression_dict_reader && block_type == BlockType::kData) {
40 CachableEntry<UncompressionDict> uncompression_dict;
20effc67
TL
41 const bool no_io = (ro.read_tier == kBlockCacheTier);
42 s = rep_->uncompression_dict_reader->GetOrReadUncompressionDictionary(
1e59de90
TL
43 prefetch_buffer, no_io, ro.verify_checksums, get_context,
44 lookup_context, &uncompression_dict);
20effc67
TL
45 if (!s.ok()) {
46 iter->Invalidate(s);
47 return iter;
48 }
1e59de90
TL
49 const UncompressionDict& dict = uncompression_dict.GetValue()
50 ? *uncompression_dict.GetValue()
51 : UncompressionDict::GetEmptyDict();
52 s = RetrieveBlock(prefetch_buffer, ro, handle, dict, &block, block_type,
53 get_context, lookup_context, for_compaction,
54 /* use_cache */ true, /* wait_for_cache */ true,
55 async_read);
56 } else {
57 s = RetrieveBlock(
58 prefetch_buffer, ro, handle, UncompressionDict::GetEmptyDict(), &block,
59 block_type, get_context, lookup_context, for_compaction,
60 /* use_cache */ true, /* wait_for_cache */ true, async_read);
20effc67
TL
61 }
62
1e59de90
TL
63 if (s.IsTryAgain() && async_read) {
64 return iter;
65 }
20effc67
TL
66
67 if (!s.ok()) {
68 assert(block.IsEmpty());
69 iter->Invalidate(s);
70 return iter;
71 }
72
73 assert(block.GetValue() != nullptr);
74
75 // Block contents are pinned and it is still pinned after the iterator
76 // is destroyed as long as cleanup functions are moved to another object,
77 // when:
78 // 1. block cache handle is set to be released in cleanup function, or
79 // 2. it's pointing to immortal source. If own_bytes is true then we are
80 // not reading data from the original source, whether immortal or not.
81 // Otherwise, the block is pinned iff the source is immortal.
82 const bool block_contents_pinned =
83 block.IsCached() ||
84 (!block.GetValue()->own_bytes() && rep_->immortal_table);
85 iter = InitBlockIterator<TBlockIter>(rep_, block.GetValue(), block_type, iter,
86 block_contents_pinned);
87
88 if (!block.IsCached()) {
1e59de90 89 if (!ro.fill_cache) {
20effc67 90 Cache* const block_cache = rep_->table_options.block_cache.get();
1e59de90
TL
91 if (block_cache) {
92 // insert a dummy record to block cache to track the memory usage
93 Cache::Handle* cache_handle = nullptr;
94 CacheKey key = CacheKey::CreateUniqueForCacheLifetime(block_cache);
95 s = block_cache->Insert(key.AsSlice(), nullptr,
96 block.GetValue()->ApproximateMemoryUsage(),
97 nullptr, &cache_handle);
98
99 if (s.ok()) {
100 assert(cache_handle != nullptr);
101 iter->RegisterCleanup(&ForceReleaseCachedEntry, block_cache,
102 cache_handle);
103 }
20effc67
TL
104 }
105 }
106 } else {
107 iter->SetCacheHandle(block.GetCacheHandle());
108 }
109
110 block.TransferTo(iter);
111
112 return iter;
113}
114
115// Convert an uncompressed data block (i.e CachableEntry<Block>)
116// into an iterator over the contents of the corresponding block.
117// If input_iter is null, new a iterator
118// If input_iter is not null, update this iter and return it
119template <typename TBlockIter>
120TBlockIter* BlockBasedTable::NewDataBlockIterator(const ReadOptions& ro,
121 CachableEntry<Block>& block,
122 TBlockIter* input_iter,
123 Status s) const {
124 PERF_TIMER_GUARD(new_table_block_iter_nanos);
125
126 TBlockIter* iter = input_iter != nullptr ? input_iter : new TBlockIter;
127 if (!s.ok()) {
128 iter->Invalidate(s);
129 return iter;
130 }
131
132 assert(block.GetValue() != nullptr);
133 // Block contents are pinned and it is still pinned after the iterator
134 // is destroyed as long as cleanup functions are moved to another object,
135 // when:
136 // 1. block cache handle is set to be released in cleanup function, or
137 // 2. it's pointing to immortal source. If own_bytes is true then we are
138 // not reading data from the original source, whether immortal or not.
139 // Otherwise, the block is pinned iff the source is immortal.
140 const bool block_contents_pinned =
141 block.IsCached() ||
142 (!block.GetValue()->own_bytes() && rep_->immortal_table);
143 iter = InitBlockIterator<TBlockIter>(rep_, block.GetValue(), BlockType::kData,
144 iter, block_contents_pinned);
145
146 if (!block.IsCached()) {
1e59de90 147 if (!ro.fill_cache) {
20effc67 148 Cache* const block_cache = rep_->table_options.block_cache.get();
1e59de90
TL
149 if (block_cache) {
150 // insert a dummy record to block cache to track the memory usage
151 Cache::Handle* cache_handle = nullptr;
152 CacheKey key = CacheKey::CreateUniqueForCacheLifetime(block_cache);
153 s = block_cache->Insert(key.AsSlice(), nullptr,
154 block.GetValue()->ApproximateMemoryUsage(),
155 nullptr, &cache_handle);
156
157 if (s.ok()) {
158 assert(cache_handle != nullptr);
159 iter->RegisterCleanup(&ForceReleaseCachedEntry, block_cache,
160 cache_handle);
161 }
20effc67
TL
162 }
163 }
164 } else {
165 iter->SetCacheHandle(block.GetCacheHandle());
166 }
167
168 block.TransferTo(iter);
169 return iter;
170}
171} // namespace ROCKSDB_NAMESPACE