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 160 : static void DeleteEntry(const Slice& key, void* value) {
20 160 : TableAndFile* tf = reinterpret_cast<TableAndFile*>(value);
21 160 : delete tf->table;
22 160 : delete tf->file;
23 160 : delete tf;
24 160 : }
25 :
26 218 : static void UnrefEntry(void* arg1, void* arg2) {
27 218 : Cache* cache = reinterpret_cast<Cache*>(arg1);
28 218 : Cache::Handle* h = reinterpret_cast<Cache::Handle*>(arg2);
29 218 : cache->Release(h);
30 218 : }
31 :
32 244 : TableCache::TableCache(const std::string& dbname,
33 : const Options* options,
34 : int entries)
35 : : env_(options->env),
36 : dbname_(dbname),
37 : options_(options),
38 244 : cache_(NewLRUCache(entries)) {
39 244 : }
40 :
41 488 : TableCache::~TableCache() {
42 244 : delete cache_;
43 244 : }
44 :
45 17108 : Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
46 : Cache::Handle** handle) {
47 : Status s;
48 : char buf[sizeof(file_number)];
49 17108 : EncodeFixed64(buf, file_number);
50 : Slice key(buf, sizeof(buf));
51 17108 : *handle = cache_->Lookup(key);
52 17108 : if (*handle == NULL) {
53 160 : std::string fname = TableFileName(dbname_, file_number);
54 160 : RandomAccessFile* file = NULL;
55 160 : Table* table = NULL;
56 320 : s = env_->NewRandomAccessFile(fname, &file);
57 160 : if (!s.ok()) {
58 0 : std::string old_fname = SSTTableFileName(dbname_, file_number);
59 0 : if (env_->NewRandomAccessFile(old_fname, &file).ok()) {
60 0 : s = Status::OK();
61 : }
62 : }
63 160 : if (s.ok()) {
64 320 : s = Table::Open(*options_, file, file_size, &table);
65 : }
66 :
67 160 : if (!s.ok()) {
68 0 : assert(table == NULL);
69 0 : delete file;
70 : // We do not cache error results so that if the error is transient,
71 : // or somebody repairs the file, we recover automatically.
72 : } else {
73 160 : TableAndFile* tf = new TableAndFile;
74 160 : tf->file = file;
75 160 : tf->table = table;
76 160 : *handle = cache_->Insert(key, tf, 1, &DeleteEntry);
77 : }
78 : }
79 17108 : return s;
80 : }
81 :
82 218 : Iterator* TableCache::NewIterator(const ReadOptions& options,
83 : uint64_t file_number,
84 : uint64_t file_size,
85 : Table** tableptr) {
86 218 : if (tableptr != NULL) {
87 0 : *tableptr = NULL;
88 : }
89 :
90 218 : Cache::Handle* handle = NULL;
91 218 : Status s = FindTable(file_number, file_size, &handle);
92 218 : if (!s.ok()) {
93 0 : return NewErrorIterator(s);
94 : }
95 :
96 218 : Table* table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
97 218 : Iterator* result = table->NewIterator(options);
98 218 : result->RegisterCleanup(&UnrefEntry, cache_, handle);
99 218 : if (tableptr != NULL) {
100 0 : *tableptr = table;
101 : }
102 218 : return result;
103 : }
104 :
105 16890 : Status TableCache::Get(const ReadOptions& options,
106 : uint64_t file_number,
107 : uint64_t file_size,
108 : const Slice& k,
109 : void* arg,
110 : void (*saver)(void*, const Slice&, const Slice&)) {
111 16890 : Cache::Handle* handle = NULL;
112 16890 : Status s = FindTable(file_number, file_size, &handle);
113 16890 : if (s.ok()) {
114 16890 : Table* t = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
115 33780 : s = t->InternalGet(options, k, arg, saver);
116 16890 : cache_->Release(handle);
117 : }
118 16890 : return s;
119 : }
120 :
121 15 : void TableCache::Evict(uint64_t file_number) {
122 : char buf[sizeof(file_number)];
123 15 : EncodeFixed64(buf, file_number);
124 30 : cache_->Erase(Slice(buf, sizeof(buf)));
125 15 : }
126 :
127 : } // namespace leveldb
|