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.
5 #include "db/table_cache.h"
7 #include "db/filename.h"
8 #include "leveldb/env.h"
9 #include "leveldb/table.h"
10 #include "util/coding.h"
15 RandomAccessFile
* file
;
19 static void DeleteEntry(const Slice
& key
, void* value
) {
20 TableAndFile
* tf
= reinterpret_cast<TableAndFile
*>(value
);
26 static void UnrefEntry(void* arg1
, void* arg2
) {
27 Cache
* cache
= reinterpret_cast<Cache
*>(arg1
);
28 Cache::Handle
* h
= reinterpret_cast<Cache::Handle
*>(arg2
);
32 TableCache::TableCache(const std::string
& dbname
,
33 const Options
* options
,
38 cache_(NewLRUCache(entries
)) {
41 TableCache::~TableCache() {
45 Status
TableCache::FindTable(uint64_t file_number
, uint64_t file_size
,
46 Cache::Handle
** handle
) {
48 char buf
[sizeof(file_number
)];
49 EncodeFixed64(buf
, file_number
);
50 Slice
key(buf
, sizeof(buf
));
51 *handle
= cache_
->Lookup(key
);
52 if (*handle
== NULL
) {
53 std::string fname
= TableFileName(dbname_
, file_number
);
54 RandomAccessFile
* file
= NULL
;
56 s
= env_
->NewRandomAccessFile(fname
, &file
);
58 std::string old_fname
= SSTTableFileName(dbname_
, file_number
);
59 if (env_
->NewRandomAccessFile(old_fname
, &file
).ok()) {
64 s
= Table::Open(*options_
, file
, file_size
, &table
);
68 assert(table
== NULL
);
70 // We do not cache error results so that if the error is transient,
71 // or somebody repairs the file, we recover automatically.
73 TableAndFile
* tf
= new TableAndFile
;
76 *handle
= cache_
->Insert(key
, tf
, 1, &DeleteEntry
);
82 Iterator
* TableCache::NewIterator(const ReadOptions
& options
,
86 if (tableptr
!= NULL
) {
90 Cache::Handle
* handle
= NULL
;
91 Status s
= FindTable(file_number
, file_size
, &handle
);
93 return NewErrorIterator(s
);
96 Table
* table
= reinterpret_cast<TableAndFile
*>(cache_
->Value(handle
))->table
;
97 Iterator
* result
= table
->NewIterator(options
);
98 result
->RegisterCleanup(&UnrefEntry
, cache_
, handle
);
99 if (tableptr
!= NULL
) {
105 Status
TableCache::Get(const ReadOptions
& options
,
106 uint64_t file_number
,
110 void (*saver
)(void*, const Slice
&, const Slice
&)) {
111 Cache::Handle
* handle
= NULL
;
112 Status s
= FindTable(file_number
, file_size
, &handle
);
114 Table
* t
= reinterpret_cast<TableAndFile
*>(cache_
->Value(handle
))->table
;
115 s
= t
->InternalGet(options
, k
, arg
, saver
);
116 cache_
->Release(handle
);
121 void TableCache::Evict(uint64_t file_number
) {
122 char buf
[sizeof(file_number
)];
123 EncodeFixed64(buf
, file_number
);
124 cache_
->Erase(Slice(buf
, sizeof(buf
)));
127 } // namespace leveldb