xref: /leveldb-1.20/db/table_cache.cc (revision f122c6df)
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 static void DeleteEntry(const Slice& key, void* value) {
20   TableAndFile* tf = reinterpret_cast<TableAndFile*>(value);
21   delete tf->table;
22   delete tf->file;
23   delete tf;
24 }
25 
26 static void UnrefEntry(void* arg1, void* arg2) {
27   Cache* cache = reinterpret_cast<Cache*>(arg1);
28   Cache::Handle* h = reinterpret_cast<Cache::Handle*>(arg2);
29   cache->Release(h);
30 }
31 
32 TableCache::TableCache(const std::string& dbname,
33                        const Options* options,
34                        int entries)
35     : env_(options->env),
36       dbname_(dbname),
37       options_(options),
38       cache_(NewLRUCache(entries)) {
39 }
40 
41 TableCache::~TableCache() {
42   delete cache_;
43 }
44 
45 Iterator* TableCache::NewIterator(const ReadOptions& options,
46                                   uint64_t file_number,
47                                   uint64_t file_size,
48                                   Table** tableptr) {
49   if (tableptr != NULL) {
50     *tableptr = NULL;
51   }
52 
53   char buf[sizeof(file_number)];
54   EncodeFixed64(buf, file_number);
55   Slice key(buf, sizeof(buf));
56   Cache::Handle* handle = cache_->Lookup(key);
57   if (handle == NULL) {
58     std::string fname = TableFileName(dbname_, file_number);
59     RandomAccessFile* file = NULL;
60     Table* table = NULL;
61     Status s = env_->NewRandomAccessFile(fname, &file);
62     if (s.ok()) {
63       s = Table::Open(*options_, file, file_size, &table);
64     }
65 
66     if (!s.ok()) {
67       assert(table == NULL);
68       delete file;
69       // We do not cache error results so that if the error is transient,
70       // or somebody repairs the file, we recover automatically.
71       return NewErrorIterator(s);
72     }
73 
74     TableAndFile* tf = new TableAndFile;
75     tf->file = file;
76     tf->table = table;
77     handle = cache_->Insert(key, tf, 1, &DeleteEntry);
78   }
79 
80   Table* table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
81   Iterator* result = table->NewIterator(options);
82   result->RegisterCleanup(&UnrefEntry, cache_, handle);
83   if (tableptr != NULL) {
84     *tableptr = table;
85   }
86   return result;
87 }
88 
89 void TableCache::Evict(uint64_t file_number) {
90   char buf[sizeof(file_number)];
91   EncodeFixed64(buf, file_number);
92   cache_->Erase(Slice(buf, sizeof(buf)));
93 }
94 
95 }
96