通过上一篇文章leveldb的Cache整体结构说明, 我们基本上知道了tableCache在整个leveldb中的作用以及上下文类关系,它主要缓存leveldb落地的ldb文件结构在内存中的信息。本篇主要是对代码流程的解读。
table_cache.h
namespace leveldb
{
class Env;
class TableCache {
public:
TableCache(const std
::string
& dbname
, const Options
& options
, int entries
);
~TableCache();
Iterator
* NewIterator(const ReadOptions
& options
, uint64_t file_number
,
uint64_t file_size
, Table
** tableptr
= nullptr);
Status
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
&));
void Evict(uint64_t file_number
);
private:
Status
FindTable(uint64_t file_number
, uint64_t file_size
, Cache
::Handle
**);
Env
* const env_
;
const std
::string dbname_
;
const Options
& options_
;
Cache
* cache_
;
};
}
table_cache.cc
namespace leveldb
{
struct TableAndFile
{
RandomAccessFile
* file
;
Table
* table
;
};
static void DeleteEntry(const Slice
& key
, void* value
) {
TableAndFile
* tf
= reinterpret_cast<TableAndFile
*>(value
);
delete tf
->table
;
delete tf
->file
;
delete tf
;
}
static void UnrefEntry(void* arg1
, void* arg2
) {
Cache
* cache
= reinterpret_cast<Cache
*>(arg1
);
Cache
::Handle
* h
= reinterpret_cast<Cache
::Handle
*>(arg2
);
cache
->Release(h
);
}
TableCache
::TableCache(const std
::string
& dbname
, const Options
& options
,
int entries
)
: env_(options
.env
),
dbname_(dbname
),
options_(options
),
cache_(NewLRUCache(entries
)) {}
TableCache
::~TableCache() { delete cache_
; }
Status TableCache
::FindTable(uint64_t file_number
, uint64_t file_size
,
Cache
::Handle
** handle
) {
Status s
;
char buf
[sizeof(file_number
)];
EncodeFixed64(buf
, file_number
);
Slice
key(buf
, sizeof(buf
));
*handle
= cache_
->Lookup(key
);
if (*handle
== nullptr) {
std
::string fname
= TableFileName(dbname_
, file_number
);
RandomAccessFile
* file
= nullptr;
Table
* table
= nullptr;
s
= env_
->NewRandomAccessFile(fname
, &file
);
if (!s
.ok()) {
std
::string old_fname
= SSTTableFileName(dbname_
, file_number
);
if (env_
->NewRandomAccessFile(old_fname
, &file
).ok()) {
s
= Status
::OK();
}
}
if (s
.ok()) {
s
= Table
::Open(options_
, file
, file_size
, &table
);
}
if (!s
.ok()) {
assert(table
== nullptr);
delete file
;
} else {
TableAndFile
* tf
= new TableAndFile
;
tf
->file
= file
;
tf
->table
= table
;
*handle
= cache_
->Insert(key
, tf
, 1, &DeleteEntry
);
}
}
return s
;
}
Iterator
* TableCache
::NewIterator(const ReadOptions
& options
,
uint64_t file_number
, uint64_t file_size
,
Table
** tableptr
) {
if (tableptr
!= nullptr) {
*tableptr
= nullptr;
}
Cache
::Handle
* handle
= nullptr;
Status s
= FindTable(file_number
, file_size
, &handle
);
if (!s
.ok()) {
return NewErrorIterator(s
);
}
Table
* table
= reinterpret_cast<TableAndFile
*>(cache_
->Value(handle
))->table
;
Iterator
* result
= table
->NewIterator(options
);
result
->RegisterCleanup(&UnrefEntry
, cache_
, handle
);
if (tableptr
!= nullptr) {
*tableptr
= table
;
}
return result
;
}
Status TableCache
::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
&)) {
Cache
::Handle
* handle
= nullptr;
Status s
= FindTable(file_number
, file_size
, &handle
);
if (s
.ok()) {
Table
* t
= reinterpret_cast<TableAndFile
*>(cache_
->Value(handle
))->table
;
s
= t
->InternalGet(options
, k
, arg
, handle_result
);
cache_
->Release(handle
);
}
return s
;
}
void TableCache
::Evict(uint64_t file_number
) {
char buf
[sizeof(file_number
)];
EncodeFixed64(buf
, file_number
);
cache_
->Erase(Slice(buf
, sizeof(buf
)));
}
}
转载请注明原文地址:https://ipadbbs.8miu.com/read-56771.html