LevelDB源码剖析之TableCache
来源:互联网 发布:歼31黑烟 知乎 编辑:程序博客网 时间:2024/06/07 06:36
原文:http://blog.csdn.net/sparkliang/article/details/8740712
7.1 TableCache简介
TableCache缓存的是Table对象,每个DB一个,它内部使用一个LRUCache缓存所有的table对象,实际上其内容是文件编号{file number, TableAndFile*}。TableAndFile是一个拥有2个变量的结构体:RandomAccessFile*和Table*;
TableCache类的主要成员变量有:
- Env* const env_; // 用来操作文件
- const std::string dbname_; // db名
- Cache* cache_; // LRUCache
三个函数接口,其中的参数@file_number是文件编号,@file_size是文件大小:
- void Evict(uint64_tfile_number);
- // 该函数用以清除指定文件所有cache的entry,函数实现很简单,就是根据file number清除cache对象。
- EncodeFixed64(buf,file_number); cache_->Erase(Slice(buf, sizeof(buf)));
- Iterator* NewIterator(constReadOptions& options, uint64_t file_number,
- uint64_t file_size, Table**tableptr = NULL);
- //该函数为指定的file返回一个iterator(对应的文件长度必须是"file_size"字节). 如果tableptr不是NULL,那么*tableptr保存的是底层的Table指针。返回的*tableptr是cache拥有的,不能被删除,生命周期同返回的iterator
- Status Get(constReadOptions& options,
- uint64_t file_number,uint64_t file_size,
- const Slice& k,void* arg,
- void(*handle_result)(void*, const Slice&, const Slice&));
- // 这是一个查找函数,如果在指定文件中seek 到internal key "k" 找到一个entry,就调用 (*handle_result)(arg,found_key, found_value).
7.2 TableCache::Get()
先来看看Get接口,只有几行代码:
- Cache::Handle* handle = NULL;
- 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, saver);
- cache_->Release(handle);
- }
- return s;
Cache在Lookup找到cache对象后,如果不再使用需要调用Release减引用计数。这个见Cache的接口说明。
7.3 TableCache遍历
函数NewIterator(),返回一个可以遍历Table对象的Iterator指针,函数逻辑:
S1 初始化tableptr,调用FindTable,返回cache对象
- if (tableptr != NULL) *tableptr =NULL;
- Cache::Handle* handle = NULL;
- Status s =FindTable(file_number, file_size, &handle);
- if (!s.ok()) returnNewErrorIterator(s);
S2 从cache对象中取出Table对象指针,调用其NewIterator返回Iterator对象,并为Iterator注册一个cleanup函数。
- Table* table =reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
- Iterator* result =table->NewIterator(options);
- result->RegisterCleanup(&UnrefEntry, cache_, handle);
- if (tableptr != NULL) *tableptr= table;
- return result;
7.4 TableCache::FindTable()
前面的遍历和Get函数都依赖于FindTable这个私有函数完成对cache的查找,下面就来看看该函数的逻辑。函数声明为:
Status FindTable(uint64_t file_number, uint64_t file_size,Cache::Handle** handle)
函数流程为:
S1 首先根据file number从cache中查找table,找到就直接返回成功。
- char buf[sizeof(file_number)];
- EncodeFixed64(buf, file_number);
- Slice key(buf, sizeof(buf));
- *handle = cache_->Lookup(key);
S2 如果没有找到,说明table不在cache中,则根据file number和db name打开一个RadomAccessFile。Table文件格式为:<db name>.<filenumber(%6u)>.sst。如果文件打开成功,则调用Table::Open读取sstable文件。
- std::string fname =TableFileName(dbname_, file_number);
- RandomAccessFile* file = NULL;
- Table* table = NULL;
- s =env_->NewRandomAccessFile(fname, &file);
- if (s.ok()) s =Table::Open(*options_, file, file_size, &table);
S3 如果Table::Open成功则,插入到Cache中。
- TableAndFile* tf = newTableAndFile(table, file);
- *handle = cache_->Insert(key,tf, 1, &DeleteEntry);
如果失败,则删除file,直接返回失败,失败的结果是不会cache的。
7.5 辅助函数
有点啰嗦,不过还是写一下吧。其中一个是为LRUCache注册的删除函数DeleteEntry。
- static void DeleteEntry(const Slice& key, void* value) {
- TableAndFile* tf =reinterpret_cast<TableAndFile*>(value);
- delete tf->table;
- delete tf->file;
- delete tf;
- }
另外一个是为Iterator注册的清除函数UnrefEntry。
- static void UnrefEntry(void* arg1, void* arg2) {
- Cache* cache =reinterpret_cast<Cache*>(arg1);
- Cache::Handle* h =reinterpret_cast<Cache::Handle*>(arg2);
- cache->Release(h);
- }
- LevelDB源码剖析之TableCache
- levelDB源码分析-TableCache
- LevelDB源码剖析之SkipList
- LevelDB源码剖析之SkipList
- LevelDB源码剖析之Log_1
- LevelDB源码剖析之Log_2
- leveldb:TableCache以及BlockCache
- LevelDB源码剖析之Memtable(1)
- LevelDB源码剖析之Memtable(2)
- leveldb源码剖析--编码
- leveldb源码剖析-sstable
- leveldb源码剖析--MemTable
- LevelDB源码剖析之Cache(HashTable LRUCache ShardedLRUCache)
- LevelDB源码剖析之SSTable_1(Block的创建与读取)
- LevelDB源码剖析之SSTable_sstable文件的创建
- LevelDB源码剖析之SSTable_sstable文件的读取
- leveldb源码剖析---filter block
- leveldb源码剖析---日志系统
- iOS开发 iOS8 适配
- 关于java'反射机制,获得类的所有方法与字段
- linux cd 命令
- Windows下安装Redis和MongoDB
- FTP命令详解
- LevelDB源码剖析之TableCache
- ORACLE高水位线
- android开发环境搭建
- 面试感悟
- php mssql 存储过程
- Monkey Test 命令使用
- window下Eclipse配置联调hadoop1.0.3集群
- linux系统用户态和内核态及其通信
- Qt常用类