Branch data Line data Source code
1 : : // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 : : // Use of this source code is governed by a BSD-style license that can be
3 : : // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 : :
5 : : #include "db/table_cache.h"
6 : :
7 : : #include "db/filename.h"
8 : : #include "leveldb/env.h"
9 : : #include "leveldb/table.h"
10 : : #include "util/coding.h"
11 : :
12 : : namespace leveldb {
13 : :
14 : : struct TableAndFile {
15 : : RandomAccessFile* file;
16 : : Table* table;
17 : : };
18 : :
19 : 155 : static void DeleteEntry(const Slice& key, void* value) {
20 : 155 : TableAndFile* tf = reinterpret_cast<TableAndFile*>(value);
21 [ + - ]: 155 : delete tf->table;
22 [ + - ]: 155 : delete tf->file;
23 [ + - ]: 155 : delete tf;
24 : 155 : }
25 : :
26 : 384 : static void UnrefEntry(void* arg1, void* arg2) {
27 : 384 : Cache* cache = reinterpret_cast<Cache*>(arg1);
28 : 384 : Cache::Handle* h = reinterpret_cast<Cache::Handle*>(arg2);
29 : 384 : cache->Release(h);
30 : 384 : }
31 : :
32 : 489 : TableCache::TableCache(const std::string& dbname, const Options& options,
33 : 489 : int entries)
34 : 489 : : env_(options.env),
35 [ - + ]: 489 : dbname_(dbname),
36 : 489 : options_(options),
37 [ + - ]: 489 : cache_(NewLRUCache(entries)) {}
38 : :
39 [ + - ]: 489 : TableCache::~TableCache() { delete cache_; }
40 : :
41 : 1292605 : Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
42 : : Cache::Handle** handle) {
43 : 1292605 : Status s;
44 : 1292605 : char buf[sizeof(file_number)];
45 : 1292605 : EncodeFixed64(buf, file_number);
46 [ + - ]: 1292605 : Slice key(buf, sizeof(buf));
47 [ + - ]: 1292605 : *handle = cache_->Lookup(key);
48 [ + + ]: 1292605 : if (*handle == nullptr) {
49 [ + - ]: 155 : std::string fname = TableFileName(dbname_, file_number);
50 : 155 : RandomAccessFile* file = nullptr;
51 : 155 : Table* table = nullptr;
52 [ + - - + ]: 155 : s = env_->NewRandomAccessFile(fname, &file);
53 [ - + ]: 155 : if (!s.ok()) {
54 [ # # ]: 0 : std::string old_fname = SSTTableFileName(dbname_, file_number);
55 [ # # # # : 0 : if (env_->NewRandomAccessFile(old_fname, &file).ok()) {
# # ]
56 [ # # ]: 0 : s = Status::OK();
57 : : }
58 : 0 : }
59 [ + - ]: 155 : if (s.ok()) {
60 [ + - - + ]: 155 : s = Table::Open(options_, file, file_size, &table);
61 : : }
62 : :
63 [ - + ]: 155 : if (!s.ok()) {
64 [ # # ]: 0 : assert(table == nullptr);
65 [ # # ]: 0 : delete file;
66 : : // We do not cache error results so that if the error is transient,
67 : : // or somebody repairs the file, we recover automatically.
68 : : } else {
69 [ + - ]: 155 : TableAndFile* tf = new TableAndFile;
70 : 155 : tf->file = file;
71 : 155 : tf->table = table;
72 [ + - ]: 155 : *handle = cache_->Insert(key, tf, 1, &DeleteEntry);
73 : : }
74 : 155 : }
75 : 1292605 : return s;
76 : 0 : }
77 : :
78 : 384 : Iterator* TableCache::NewIterator(const ReadOptions& options,
79 : : uint64_t file_number, uint64_t file_size,
80 : : Table** tableptr) {
81 [ + + ]: 384 : if (tableptr != nullptr) {
82 : 110 : *tableptr = nullptr;
83 : : }
84 : :
85 : 384 : Cache::Handle* handle = nullptr;
86 : 384 : Status s = FindTable(file_number, file_size, &handle);
87 [ - + ]: 384 : if (!s.ok()) {
88 [ # # ]: 0 : return NewErrorIterator(s);
89 : : }
90 : :
91 [ + - ]: 384 : Table* table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
92 [ + - ]: 384 : Iterator* result = table->NewIterator(options);
93 [ + - ]: 384 : result->RegisterCleanup(&UnrefEntry, cache_, handle);
94 [ + + ]: 384 : if (tableptr != nullptr) {
95 : 110 : *tableptr = table;
96 : : }
97 : : return result;
98 : 384 : }
99 : :
100 : 1292221 : Status TableCache::Get(const ReadOptions& options, uint64_t file_number,
101 : : uint64_t file_size, const Slice& k, void* arg,
102 : : void (*handle_result)(void*, const Slice&,
103 : : const Slice&)) {
104 : 1292221 : Cache::Handle* handle = nullptr;
105 : 1292221 : Status s = FindTable(file_number, file_size, &handle);
106 [ + - ]: 1292221 : if (s.ok()) {
107 [ + - ]: 1292221 : Table* t = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
108 [ + - - + ]: 1292221 : s = t->InternalGet(options, k, arg, handle_result);
109 [ + - ]: 1292221 : cache_->Release(handle);
110 : : }
111 : 1292221 : return s;
112 : 0 : }
113 : :
114 : 45 : void TableCache::Evict(uint64_t file_number) {
115 : 45 : char buf[sizeof(file_number)];
116 : 45 : EncodeFixed64(buf, file_number);
117 : 45 : cache_->Erase(Slice(buf, sizeof(buf)));
118 : 45 : }
119 : :
120 : : } // namespace leveldb
|