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