/Users/deen/code/yugabyte-db/src/yb/rocksdb/db/table_cache.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under the BSD-style license found in the |
3 | | // LICENSE file in the root directory of this source tree. An additional grant |
4 | | // of patent rights can be found in the PATENTS file in the same directory. |
5 | | // |
6 | | // The following only applies to changes made to this file as part of YugaByte development. |
7 | | // |
8 | | // Portions Copyright (c) YugaByte, Inc. |
9 | | // |
10 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
11 | | // in compliance with the License. You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
16 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
17 | | // or implied. See the License for the specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
21 | | // Use of this source code is governed by a BSD-style license that can be |
22 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
23 | | |
24 | | #include "yb/rocksdb/db/table_cache.h" |
25 | | |
26 | | #include "yb/rocksdb/db/dbformat.h" |
27 | | #include "yb/rocksdb/db/filename.h" |
28 | | #include "yb/rocksdb/db/version_edit.h" |
29 | | #include "yb/rocksdb/statistics.h" |
30 | | #include "yb/rocksdb/table.h" |
31 | | #include "yb/rocksdb/table/get_context.h" |
32 | | #include "yb/rocksdb/table/internal_iterator.h" |
33 | | #include "yb/rocksdb/table/iterator_wrapper.h" |
34 | | #include "yb/rocksdb/table/table_builder.h" |
35 | | #include "yb/rocksdb/table/table_reader.h" |
36 | | #include "yb/rocksdb/util/coding.h" |
37 | | #include "yb/rocksdb/util/file_reader_writer.h" |
38 | | #include "yb/rocksdb/util/perf_context_imp.h" |
39 | | #include "yb/rocksdb/util/sync_point.h" |
40 | | |
41 | | #include "yb/util/logging.h" |
42 | | #include "yb/util/stats/perf_step_timer.h" |
43 | | |
44 | | namespace rocksdb { |
45 | | |
46 | | namespace { |
47 | | |
48 | | template <class T> |
49 | 116k | static void DeleteEntry(const Slice& key, void* value) { |
50 | 116k | T* typed_value = reinterpret_cast<T*>(value); |
51 | 116k | delete typed_value; |
52 | 116k | } table_cache.cc:void rocksdb::(anonymous namespace)::DeleteEntry<rocksdb::TableReader>(yb::Slice const&, void*) Line | Count | Source | 49 | 74.0k | static void DeleteEntry(const Slice& key, void* value) { | 50 | 74.0k | T* typed_value = reinterpret_cast<T*>(value); | 51 | 74.0k | delete typed_value; | 52 | 74.0k | } |
table_cache.cc:void rocksdb::(anonymous namespace)::DeleteEntry<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(yb::Slice const&, void*) Line | Count | Source | 49 | 42.2k | static void DeleteEntry(const Slice& key, void* value) { | 50 | 42.2k | T* typed_value = reinterpret_cast<T*>(value); | 51 | 42.2k | delete typed_value; | 52 | 42.2k | } |
|
53 | | |
54 | 14.6M | static void UnrefEntry(void* arg1, void* arg2) { |
55 | 14.6M | Cache* cache = reinterpret_cast<Cache*>(arg1); |
56 | 14.6M | Cache::Handle* h = reinterpret_cast<Cache::Handle*>(arg2); |
57 | 14.6M | cache->Release(h); |
58 | 14.6M | } |
59 | | |
60 | 466 | static void DeleteTableReader(void* arg1, void* arg2) { |
61 | 466 | TableReader* table_reader = reinterpret_cast<TableReader*>(arg1); |
62 | 466 | delete table_reader; |
63 | 466 | } |
64 | | |
65 | 29.1M | static Slice GetSliceForFileNumber(const uint64_t* file_number) { |
66 | 29.1M | return Slice(reinterpret_cast<const char*>(file_number), |
67 | 29.1M | sizeof(*file_number)); |
68 | 29.1M | } |
69 | | |
70 | | #ifndef ROCKSDB_LITE |
71 | | |
72 | 102k | void AppendVarint64(IterKey* key, uint64_t v) { |
73 | 102k | char buf[10]; |
74 | 102k | auto ptr = EncodeVarint64(buf, v); |
75 | 102k | key->TrimAppend(key->Size(), buf, ptr - buf); |
76 | 102k | } |
77 | | |
78 | | #endif // ROCKSDB_LITE |
79 | | |
80 | | } // namespace |
81 | | |
82 | | TableCache::TableCache(const ImmutableCFOptions& ioptions, |
83 | | const EnvOptions& env_options, Cache* const cache) |
84 | 441k | : ioptions_(ioptions), env_options_(env_options), cache_(cache) { |
85 | 441k | if (ioptions_.row_cache) { |
86 | | // If the same cache is shared by multiple instances, we need to |
87 | | // disambiguate its entries. |
88 | 332 | PutVarint64(&row_cache_id_, ioptions_.row_cache->NewId()); |
89 | 332 | } |
90 | 441k | } |
91 | | |
92 | 402k | TableCache::~TableCache() { |
93 | 402k | } |
94 | | |
95 | 29.0M | TableReader* TableCache::GetTableReaderFromHandle(Cache::Handle* handle) { |
96 | 29.0M | return reinterpret_cast<TableReader*>(cache_->Value(handle)); |
97 | 29.0M | } |
98 | | |
99 | 8.28M | void TableCache::ReleaseHandle(Cache::Handle* handle) { |
100 | 8.28M | cache_->Release(handle); |
101 | 8.28M | } |
102 | | |
103 | | namespace { |
104 | | |
105 | | Status NewFileReader(const ImmutableCFOptions& ioptions, const EnvOptions& env_options, |
106 | | const std::string& fname, bool sequential_mode, bool record_read_stats, |
107 | 151k | HistogramImpl* file_read_hist, std::unique_ptr<RandomAccessFileReader>* file_reader) { |
108 | 151k | unique_ptr<RandomAccessFile> file; |
109 | | |
110 | 151k | Status s = ioptions.env->NewRandomAccessFile(fname, &file, env_options); |
111 | 151k | if (!s.ok()) { |
112 | 542 | return s; |
113 | 542 | } |
114 | 150k | RecordTick(ioptions.statistics, NO_FILE_OPENS); |
115 | | |
116 | 150k | if (sequential_mode && ioptions.compaction_readahead_size > 0932 ) { |
117 | 924 | file = NewReadaheadRandomAccessFile(std::move(file), ioptions.compaction_readahead_size); |
118 | 924 | } |
119 | 150k | if (!sequential_mode && ioptions.advise_random_on_open150k ) { |
120 | 150k | file->Hint(RandomAccessFile::RANDOM); |
121 | 150k | } |
122 | | |
123 | 150k | file_reader->reset(new RandomAccessFileReader( |
124 | 150k | std::move(file), |
125 | 150k | ioptions.env, |
126 | 150k | record_read_stats ? ioptions.statistics150k : nullptr936 , |
127 | 150k | SST_READ_MICROS, |
128 | 150k | file_read_hist)); |
129 | 150k | return Status::OK(); |
130 | 151k | } |
131 | | |
132 | | } // anonymous namespace |
133 | | |
134 | | Status TableCache::DoGetTableReader( |
135 | | const EnvOptions& env_options, |
136 | | const InternalKeyComparatorPtr& internal_comparator, const FileDescriptor& fd, |
137 | | bool sequential_mode, bool record_read_stats, HistogramImpl* file_read_hist, |
138 | 77.2k | unique_ptr<TableReader>* table_reader, bool skip_filters) { |
139 | 77.2k | const std::string base_fname = TableFileName(ioptions_.db_paths, fd.GetNumber(), fd.GetPathId()); |
140 | | |
141 | 77.2k | Status s; |
142 | 77.2k | { |
143 | 77.2k | unique_ptr<RandomAccessFileReader> base_file_reader; |
144 | 77.2k | s = NewFileReader(ioptions_, env_options, base_fname, sequential_mode, record_read_stats, |
145 | 77.2k | file_read_hist, &base_file_reader); |
146 | 77.2k | if (!s.ok()) { |
147 | 542 | return s; |
148 | 542 | } |
149 | 76.7k | s = ioptions_.table_factory->NewTableReader( |
150 | 76.7k | TableReaderOptions(ioptions_, env_options, internal_comparator, skip_filters), |
151 | 76.7k | std::move(base_file_reader), fd.GetBaseFileSize(), table_reader); |
152 | 76.7k | if (!s.ok()) { |
153 | 34 | return s; |
154 | 34 | } |
155 | 76.7k | } |
156 | | |
157 | 76.6k | if ((*table_reader)->IsSplitSst()) { |
158 | 74.2k | const std::string data_fname = TableBaseToDataFileName(base_fname); |
159 | 74.2k | std::unique_ptr<RandomAccessFileReader> data_file_reader; |
160 | 74.2k | s = NewFileReader(ioptions_, env_options, data_fname, sequential_mode, record_read_stats, |
161 | 74.2k | file_read_hist, &data_file_reader); |
162 | 74.2k | if (!s.ok()) { |
163 | 0 | return s; |
164 | 0 | } |
165 | 74.2k | (*table_reader)->SetDataFileReader(std::move(data_file_reader)); |
166 | 74.2k | } |
167 | 76.6k | TEST_SYNC_POINT("TableCache::GetTableReader:0"); |
168 | 76.6k | return s; |
169 | 76.6k | } |
170 | | |
171 | | Status TableCache::FindTable(const EnvOptions& env_options, |
172 | | const InternalKeyComparatorPtr& internal_comparator, |
173 | | const FileDescriptor& fd, Cache::Handle** handle, |
174 | | const QueryId query_id, const bool no_io, bool record_read_stats, |
175 | 29.0M | HistogramImpl* file_read_hist, bool skip_filters) { |
176 | 29.0M | PERF_TIMER_GUARD(find_table_nanos); |
177 | 29.0M | Status s; |
178 | 29.0M | uint64_t number = fd.GetNumber(); |
179 | 29.0M | Slice key = GetSliceForFileNumber(&number); |
180 | 29.0M | *handle = cache_->Lookup(key, query_id); |
181 | 29.0M | TEST_SYNC_POINT_CALLBACK("TableCache::FindTable:0", |
182 | 29.0M | const_cast<bool*>(&no_io)); |
183 | | |
184 | 29.0M | if (*handle == nullptr) { |
185 | 107k | if (no_io) { // Don't do IO and return a not-found status |
186 | 31.1k | return STATUS(Incomplete, "Table not found in table_cache, no_io is set"); |
187 | 31.1k | } |
188 | 76.8k | unique_ptr<TableReader> table_reader; |
189 | 76.8k | s = DoGetTableReader(env_options, internal_comparator, fd, |
190 | 76.8k | false /* sequential mode */, record_read_stats, |
191 | 76.8k | file_read_hist, &table_reader, skip_filters); |
192 | 76.8k | if (!s.ok()) { |
193 | 576 | assert(table_reader == nullptr); |
194 | 0 | RecordTick(ioptions_.statistics, NO_FILE_ERRORS); |
195 | | // We do not cache error results so that if the error is transient, |
196 | | // or somebody repairs the file, we recover automatically. |
197 | 76.2k | } else { |
198 | 76.2k | s = cache_->Insert(key, query_id, table_reader.get(), 1, &DeleteEntry<TableReader>, handle); |
199 | 76.2k | if (s.ok()) { |
200 | | // Release ownership of table reader. |
201 | 76.2k | table_reader.release(); |
202 | 76.2k | } |
203 | 76.2k | } |
204 | 76.8k | } |
205 | 29.0M | return s; |
206 | 29.0M | } |
207 | | |
208 | | TableCache::TableReaderWithHandle::TableReaderWithHandle(TableReaderWithHandle&& rhs) |
209 | | : table_reader(rhs.table_reader), handle(rhs.handle), cache(rhs.cache), |
210 | 41.5M | created_new(rhs.created_new) { |
211 | 41.5M | rhs.Release(); |
212 | 41.5M | } |
213 | | |
214 | | TableCache::TableReaderWithHandle& TableCache::TableReaderWithHandle::operator=( |
215 | 20.7M | TableReaderWithHandle&& rhs) { |
216 | 20.7M | if (&rhs != this20.7M ) { |
217 | 20.7M | Reset(); |
218 | 20.7M | table_reader = rhs.table_reader; |
219 | 20.7M | handle = rhs.handle; |
220 | 20.7M | cache = rhs.cache; |
221 | 20.7M | created_new = rhs.created_new; |
222 | 20.7M | rhs.Release(); |
223 | 20.7M | } |
224 | 20.7M | return *this; |
225 | 20.7M | } |
226 | | |
227 | 76.9M | void TableCache::TableReaderWithHandle::Release() { |
228 | 76.9M | table_reader = nullptr; |
229 | 76.9M | handle = nullptr; |
230 | 76.9M | cache = nullptr; |
231 | 76.9M | created_new = false; |
232 | 76.9M | } |
233 | | |
234 | 103M | void TableCache::TableReaderWithHandle::Reset() { |
235 | | // TODO: can we remove created_new and check !handle instead? |
236 | 103M | if (created_new) { |
237 | 0 | DCHECK(handle == nullptr); |
238 | 0 | delete table_reader; |
239 | 103M | } else if (handle != nullptr) { |
240 | 6.14M | DCHECK_ONLY_NOTNULL(cache); |
241 | 6.14M | cache->Release(handle); |
242 | 6.14M | } |
243 | 103M | } |
244 | | |
245 | 83.1M | TableCache::TableReaderWithHandle::~TableReaderWithHandle() { |
246 | 83.1M | Reset(); |
247 | 83.1M | } |
248 | | |
249 | | Status TableCache::DoGetTableReaderForIterator( |
250 | | const ReadOptions& options, |
251 | | const EnvOptions& env_options, |
252 | | const InternalKeyComparatorPtr& icomparator, |
253 | | const FileDescriptor& fd, TableReaderWithHandle* trwh, |
254 | | HistogramImpl* file_read_hist, |
255 | | bool for_compaction, |
256 | 20.7M | bool skip_filters) { |
257 | 20.7M | const bool create_new_table_reader = |
258 | 20.7M | (for_compaction && ioptions_.new_table_reader_for_compaction_inputs48.1k ); |
259 | 20.7M | if (create_new_table_reader) { |
260 | 466 | unique_ptr<TableReader> table_reader_unique_ptr; |
261 | 466 | Status s = DoGetTableReader( |
262 | 466 | env_options, icomparator, fd, /* sequential mode */ true, |
263 | 466 | /* record stats */ false, nullptr, &table_reader_unique_ptr); |
264 | 466 | if (!s.ok()) { |
265 | 0 | return s; |
266 | 0 | } |
267 | 466 | trwh->table_reader = table_reader_unique_ptr.release(); |
268 | 20.7M | } else { |
269 | 20.7M | *trwh = VERIFY_RESULT20.7M (GetTableReader( |
270 | 20.7M | env_options, icomparator, fd, options.query_id, |
271 | 20.7M | /* no_io =*/ options.read_tier == kBlockCacheTier, file_read_hist, skip_filters)); |
272 | 20.7M | } |
273 | 20.7M | trwh->created_new = create_new_table_reader; |
274 | 20.7M | return Status::OK(); |
275 | 20.7M | } |
276 | | |
277 | | Status TableCache::GetTableReaderForIterator( |
278 | | const ReadOptions& options, const EnvOptions& env_options, |
279 | | const InternalKeyComparatorPtr& icomparator, const FileDescriptor& fd, |
280 | | TableReaderWithHandle* trwh, |
281 | 20.5M | HistogramImpl* file_read_hist, bool for_compaction, bool skip_filters) { |
282 | 20.5M | PERF_TIMER_GUARD(new_table_iterator_nanos); |
283 | 20.5M | return DoGetTableReaderForIterator(options, env_options, icomparator, fd, trwh, file_read_hist, |
284 | 20.5M | for_compaction, skip_filters); |
285 | 20.5M | } |
286 | | |
287 | | InternalIterator* TableCache::NewIterator( |
288 | | const ReadOptions& options, TableReaderWithHandle* trwh, const Slice& filter, |
289 | 14.3M | bool for_compaction, Arena* arena, bool skip_filters) { |
290 | 14.3M | PERF_TIMER_GUARD(new_table_iterator_nanos); |
291 | 14.3M | return DoNewIterator(options, trwh, filter, for_compaction, arena, skip_filters); |
292 | 14.3M | } |
293 | | |
294 | | InternalIterator* TableCache::DoNewIterator( |
295 | | const ReadOptions& options, TableReaderWithHandle* trwh, const Slice& filter, |
296 | 14.6M | bool for_compaction, Arena* arena, bool skip_filters) { |
297 | 14.6M | RecordTick(ioptions_.statistics, NO_TABLE_CACHE_ITERATORS); |
298 | | |
299 | 14.6M | InternalIterator* result = |
300 | 14.6M | trwh->table_reader->NewIterator(options, arena, skip_filters); |
301 | | |
302 | 14.6M | if (trwh->created_new) { |
303 | 466 | DCHECK(trwh->handle == nullptr); |
304 | 466 | result->RegisterCleanup(&DeleteTableReader, trwh->table_reader, nullptr); |
305 | 14.6M | } else if (trwh->handle != nullptr) { |
306 | 14.6M | result->RegisterCleanup(&UnrefEntry, cache_, trwh->handle); |
307 | 14.6M | } |
308 | | |
309 | 14.6M | if (for_compaction) { |
310 | 48.1k | trwh->table_reader->SetupForCompaction(); |
311 | 48.1k | } |
312 | | |
313 | 14.6M | if (ioptions_.iterator_replacer) { |
314 | 14.2M | result = (*ioptions_.iterator_replacer)(result, arena, filter); |
315 | 14.2M | } |
316 | | |
317 | 14.6M | trwh->Release(); |
318 | | |
319 | 14.6M | return result; |
320 | 14.6M | } |
321 | | |
322 | | InternalIterator* TableCache::NewIterator( |
323 | | const ReadOptions& options, const EnvOptions& env_options, |
324 | | const InternalKeyComparatorPtr& icomparator, const FileDescriptor& fd, const Slice& filter, |
325 | | TableReader** table_reader_ptr, HistogramImpl* file_read_hist, |
326 | 255k | bool for_compaction, Arena* arena, bool skip_filters) { |
327 | 255k | PERF_TIMER_GUARD(new_table_iterator_nanos); |
328 | | |
329 | 255k | if (table_reader_ptr != nullptr) { |
330 | 16.8k | *table_reader_ptr = nullptr; |
331 | 16.8k | } |
332 | | |
333 | 255k | TableReaderWithHandle trwh; |
334 | 255k | Status s = DoGetTableReaderForIterator(options, env_options, icomparator, fd, &trwh, |
335 | 255k | file_read_hist, for_compaction, skip_filters); |
336 | 255k | if (!s.ok()) { |
337 | 33 | return NewErrorInternalIterator(s, arena); |
338 | 33 | } |
339 | | |
340 | 255k | if (table_reader_ptr != nullptr) { |
341 | 16.8k | *table_reader_ptr = trwh.table_reader; |
342 | 16.8k | } |
343 | | |
344 | 255k | InternalIterator* result = DoNewIterator( |
345 | 255k | options, &trwh, filter, for_compaction, arena, skip_filters); |
346 | | |
347 | 255k | return result; |
348 | 255k | } |
349 | | |
350 | | Status TableCache::Get(const ReadOptions& options, |
351 | | const InternalKeyComparatorPtr& internal_comparator, |
352 | | const FileDescriptor& fd, const Slice& k, |
353 | | GetContext* get_context, HistogramImpl* file_read_hist, |
354 | 8.25M | bool skip_filters) { |
355 | 8.25M | TableReader* t = fd.table_reader; |
356 | 8.25M | Status s; |
357 | 8.25M | Cache::Handle* handle = nullptr; |
358 | 8.25M | std::string* row_cache_entry = nullptr; |
359 | | |
360 | 8.25M | #ifndef ROCKSDB_LITE |
361 | 8.25M | IterKey row_cache_key; |
362 | 8.25M | std::string row_cache_entry_buffer; |
363 | | |
364 | | // Check row cache if enabled. Since row cache does not currently store |
365 | | // sequence numbers, we cannot use it if we need to fetch the sequence. |
366 | 8.25M | if (ioptions_.row_cache && !get_context->NeedToReadSequence()51.2k ) { |
367 | 51.2k | uint64_t fd_number = fd.GetNumber(); |
368 | 51.2k | auto user_key = ExtractUserKey(k); |
369 | | // We use the user key as cache key instead of the internal key, |
370 | | // otherwise the whole cache would be invalidated every time the |
371 | | // sequence key increases. However, to support caching snapshot |
372 | | // reads, we append the sequence number (incremented by 1 to |
373 | | // distinguish from 0) only in this case. |
374 | 51.2k | uint64_t seq_no = |
375 | 51.2k | options.snapshot == nullptr ? 051.2k : 1 + GetInternalKeySeqno(k)23 ; |
376 | | |
377 | | // Compute row cache key. |
378 | 51.2k | row_cache_key.TrimAppend(row_cache_key.Size(), row_cache_id_.data(), |
379 | 51.2k | row_cache_id_.size()); |
380 | 51.2k | AppendVarint64(&row_cache_key, fd_number); |
381 | 51.2k | AppendVarint64(&row_cache_key, seq_no); |
382 | 51.2k | row_cache_key.TrimAppend(row_cache_key.Size(), user_key.cdata(), |
383 | 51.2k | user_key.size()); |
384 | | |
385 | 51.2k | if (auto row_handle = ioptions_.row_cache->Lookup(row_cache_key.GetKey(), options.query_id)) { |
386 | 6.63k | auto found_row_cache_entry = static_cast<const std::string*>( |
387 | 6.63k | ioptions_.row_cache->Value(row_handle)); |
388 | 6.63k | replayGetContextLog(*found_row_cache_entry, user_key, get_context); |
389 | 6.63k | ioptions_.row_cache->Release(row_handle); |
390 | 6.63k | RecordTick(ioptions_.statistics, ROW_CACHE_HIT); |
391 | 6.63k | return Status::OK(); |
392 | 6.63k | } |
393 | | |
394 | | // Not found, setting up the replay log. |
395 | 44.5k | RecordTick(ioptions_.statistics, ROW_CACHE_MISS); |
396 | 44.5k | row_cache_entry = &row_cache_entry_buffer; |
397 | 44.5k | } |
398 | 8.25M | #endif // ROCKSDB_LITE |
399 | | |
400 | 8.25M | if (!t) { |
401 | 8.20M | s = FindTable(env_options_, internal_comparator, fd, &handle, |
402 | 8.20M | options.query_id, options.read_tier == kBlockCacheTier /* no_io */, |
403 | 8.20M | true /* record_read_stats */, file_read_hist, skip_filters); |
404 | 8.20M | if (s.ok()) { |
405 | 8.20M | t = GetTableReaderFromHandle(handle); |
406 | 8.20M | } |
407 | 8.20M | } |
408 | 8.25M | if (s.ok()) { |
409 | 8.25M | get_context->SetReplayLog(row_cache_entry); // nullptr if no cache. |
410 | 8.25M | s = t->Get(options, k, get_context, skip_filters); |
411 | 8.25M | get_context->SetReplayLog(nullptr); |
412 | 8.25M | if (handle != nullptr) { |
413 | 8.20M | ReleaseHandle(handle); |
414 | 8.20M | } |
415 | 8.25M | } else if (459 options.read_tier == kBlockCacheTier459 && s.IsIncomplete()100 ) { |
416 | | // Couldn't find Table in cache but treat as kFound if no_io set |
417 | 100 | get_context->MarkKeyMayExist(); |
418 | 100 | return Status::OK(); |
419 | 100 | } |
420 | | |
421 | 8.25M | #ifndef ROCKSDB_LITE |
422 | | // Put the replay log in row cache only if something was found. |
423 | 8.25M | if (s.ok() && row_cache_entry8.25M && !row_cache_entry->empty()44.5k ) { |
424 | 42.2k | size_t charge = |
425 | 42.2k | row_cache_key.Size() + row_cache_entry->size() + sizeof(std::string); |
426 | 42.2k | void* row_ptr = new std::string(std::move(*row_cache_entry)); |
427 | 42.2k | s = ioptions_.row_cache->Insert(row_cache_key.GetKey(), options.query_id, row_ptr, charge, |
428 | 42.2k | &DeleteEntry<std::string>); |
429 | 42.2k | } |
430 | 8.25M | #endif // ROCKSDB_LITE |
431 | | |
432 | 8.25M | return s; |
433 | 8.25M | } |
434 | | |
435 | | yb::Result<TableCache::TableReaderWithHandle> TableCache::GetTableReader( |
436 | | const EnvOptions& env_options, const InternalKeyComparatorPtr& internal_comparator, |
437 | | const FileDescriptor& fd, const QueryId query_id, const bool no_io, |
438 | 20.7M | HistogramImpl* file_read_hist, const bool skip_filters) { |
439 | 20.7M | TableReaderWithHandle trwh; |
440 | 20.7M | trwh.table_reader = fd.table_reader; |
441 | 20.7M | if (trwh.table_reader == nullptr) { |
442 | 20.7M | RETURN_NOT_OK(FindTable( |
443 | 20.7M | env_options, internal_comparator, fd, &trwh.handle, query_id, no_io, |
444 | 20.7M | /* record_read_stats =*/ true, file_read_hist, skip_filters)); |
445 | 20.7M | trwh.table_reader = GetTableReaderFromHandle(trwh.handle); |
446 | 20.7M | trwh.cache = cache_; |
447 | 20.7M | } |
448 | 20.7M | return trwh; |
449 | 20.7M | } |
450 | | |
451 | | Status TableCache::GetTableProperties( |
452 | | const EnvOptions& env_options, |
453 | | const InternalKeyComparatorPtr& internal_comparator, const FileDescriptor& fd, |
454 | 105k | std::shared_ptr<const TableProperties>* properties, bool no_io) { |
455 | 105k | Status s; |
456 | 105k | auto table_reader = fd.table_reader; |
457 | | // table already been pre-loaded? |
458 | 105k | if (table_reader) { |
459 | 1.16k | *properties = table_reader->GetTableProperties(); |
460 | | |
461 | 1.16k | return s; |
462 | 1.16k | } |
463 | | |
464 | 104k | Cache::Handle* table_handle = nullptr; |
465 | 104k | s = FindTable(env_options, internal_comparator, fd, &table_handle, kDefaultQueryId, no_io); |
466 | 104k | if (!s.ok()) { |
467 | 31.0k | return s; |
468 | 31.0k | } |
469 | 73.1k | assert(table_handle); |
470 | 0 | auto table = GetTableReaderFromHandle(table_handle); |
471 | 73.1k | *properties = table->GetTableProperties(); |
472 | 73.1k | ReleaseHandle(table_handle); |
473 | 73.1k | return s; |
474 | 104k | } |
475 | | |
476 | | size_t TableCache::GetMemoryUsageByTableReader( |
477 | | const EnvOptions& env_options, |
478 | | const InternalKeyComparatorPtr& internal_comparator, |
479 | 80 | const FileDescriptor& fd) { |
480 | 80 | Status s; |
481 | 80 | auto table_reader = fd.table_reader; |
482 | | // table already been pre-loaded? |
483 | 80 | if (table_reader) { |
484 | 0 | return table_reader->ApproximateMemoryUsage(); |
485 | 0 | } |
486 | | |
487 | 80 | Cache::Handle* table_handle = nullptr; |
488 | 80 | s = FindTable(env_options, internal_comparator, fd, &table_handle, kDefaultQueryId, true); |
489 | 80 | if (!s.ok()) { |
490 | 3 | return 0; |
491 | 3 | } |
492 | 77 | assert(table_handle); |
493 | 0 | auto table = GetTableReaderFromHandle(table_handle); |
494 | 77 | auto ret = table->ApproximateMemoryUsage(); |
495 | 77 | ReleaseHandle(table_handle); |
496 | 77 | return ret; |
497 | 80 | } |
498 | | |
499 | 49.7k | void TableCache::Evict(Cache* cache, uint64_t file_number) { |
500 | 49.7k | cache->Erase(GetSliceForFileNumber(&file_number)); |
501 | 49.7k | } |
502 | | |
503 | | } // namespace rocksdb |