关于leveldb源码整理之三
来源:互联网 发布:python instance类型 编辑:程序博客网 时间:2024/06/16 06:25
前言
昨天写了一篇,本来想看点具体的关于真的数据中的源码的问题,可是发现,时间有限,昨天只是,看了下测试的代码,今天我们就搞真的关于数据中数据的编码问题。
正文
工欲善其事必先利其器,我们这里因为需要添加一些测试代码,所以编译机会比较多,我们在我们的makefile中加入一句:
.PHONY: testtest: $(STATIC_OUTDIR)/dbformat_test
以后每次阅读关于dbformatetest的代码时候,就可以直接make test了。
我们进入昨天一小段代码继续看
ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), ShortSuccessor(IKey("foo", 100, kTypeValue)));
这里我们知道这个ASSERT_TEST
就是判断传入的参数是不是一样。我们可以进入本篇博客的问题空间了。这里我们可以了解到kMaxSequenceNumber
是56个1,打小在这里毫无意义,就反正很大很大,kTypeValue
为1.
看下IKey
函数到底干了啥,这里我们一一追踪。首先
static std::string IKey(const std::string& user_key, uint64_t seq, ValueType vt) { std::string encoded; AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt)); return encoded;}
这里我们先解决下ParsedInternalKey
这个函数干了啥。这个函数其实干的事情很少,这是一个结构体的构造函数:
ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) : user_key(u), sequence(seq), type(t) { fprintf(stderr, "==== Test %s\n", "ParsedInternalKey"); }
这里有个问题,我们传入的是个std::string数据,但是最后变成Slice,因为我们会发现Slice有个string为参数的构造函数,这里很容易想到是编译器直接改变传入参数的。这里这个特性,大概就是这个道理,关于Slice的功能,这里就不详细介绍,很简单。这个构造函数,其实就是把传入的三个参数,都保存在三个变量中:
Slice user_key; SequenceNumber sequence; ValueType type;
这里我们很容易的知道这里是干啥的,可以暂时记住,这里要作为参数传入关键的函数,进行编码,我们开始我们本次博客的正餐。
void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { result->append(key.user_key.data(), key.user_key.size()); //result = g PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); //result = g +上 (key.sequence << 8) | 1 转换成16进制数。编码格式是ASSIC.}
这里就是函数的追踪,其实没啥特殊的,这里也许你们会骂娘,可是事实上,只有这么多东西,
这里只是进行了一种编码方式,我们继续第二种:
static std::string ShortSuccessor(const std::string& s) { std::string result = s; InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result); return result;}ShortSuccessor(IKey("foo", 100, kTypeValue)));
IKey("foo", 100, kTypeValue)
这个东西最后生成了“foo+后面的数字的特殊编码”,为11位。我们开始看我们的ShortSuccessor
BytewiseComparator()这个函数是个单例模式,线程安全,具体什么单利模式我也忘记了,反正就是线程安全的单例模式。最终生成了一个BytewiseComparatorImpl这个类,
InternalKeyComparator这个类的构造函数
explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) { }
是不是超级简单,那就不要多说了,总之就是持有一个BytewiseComparatorImpl
,关键是最后的这个内部函数我们继续看
void InternalKeyComparator::FindShortSuccessor(std::string* key) const { Slice user_key = ExtractUserKey(*key); std::string tmp(user_key.data(), user_key.size()); std::cout<<user_key.ToString()<<"FindShortestSeparator"<<tmp<<std::endl; user_comparator_->FindShortSuccessor(&tmp); std::cout<<user_key.ToString()<<"FindShortestSeparator"<<tmp<<std::endl; if (tmp.size() < user_key.size() && user_comparator_->Compare(user_key, tmp) < 0) { // User key has become shorter physically, but larger logically. // Tack on the earliest possible number to the shortened user key. PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); assert(this->Compare(*key, tmp) < 0); key->swap(tmp); }}
其实这里用了代理者模式,吧关键人物交给刚才我们的那个IMPL类,具体处理的代码如下:
virtual void FindShortSuccessor(std::string* key) const { // Find first character that can be incremented size_t n = key->size(); for (size_t i = 0; i < n; i++) { const uint8_t byte = (*key)[i]; if (byte != static_cast<uint8_t>(0xff)) { (*key)[i] = byte + 1; key->resize(i+1); return; } } // *key is a run of 0xffs. Leave it alone. }
这里处理比较奇怪,吧key作为一个数组,每个字符加1,然后去掉结尾,这里这种用法,很奇怪我暂时不能解释清楚,反正,就是这个指针的指向了一个g(f+1),
至此这个测试函数完全就通了,g==g为真。
后记
写这个系列的博客,也是费劲了心思,c++太多奇怪的特性,我也是醉了。不过总体来说收获还是挺大的,关于变量作用域和其他的一些问题,暂时我也说不清楚,因为这套代码,不是严格意义上的面相对象的代码。充斥着大量的c相关的代码,所以我们还是跟踪主要流程,一些语法细节,以后慢慢总结。
- 关于leveldb源码整理之三
- 关于leveldb源码整理之二
- 关于leveldb源码整理之一
- LevelDB源码之三SSTable
- LevelDB源码分析之三:arena
- LevelDB源码之SkipList原理LevelDB源码之SkipList原理
- LevelDB源码之SkipList原理
- LevelDB源码之SkipList原理
- LevelDB源码之SkipList原理
- LevelDB源码剖析之SkipList
- LevelDB源码剖析之SkipList
- LevelDB源码剖析之Log_1
- LevelDB源码剖析之Log_2
- LevelDB源码剖析之TableCache
- Leveldb源码分析之Slice
- leveldb源码分析之五
- levelDB之三:log文件
- leveldb源码分析 之 入门使用
- Windows 下安装NDK
- JavaSwing_4.4: JColorChooser(颜色选择器)
- Unity 3D之UI设置父子关系setParent坑
- 剖析整数,浮点数在内存中的存储
- NYOJ 86. 找球号
- 关于leveldb源码整理之三
- LeetCode | 174. Dungeon Game (Hard)
- Linux 网卡驱动学习(六)(应用层、tcp 层、ip 层、设备层和驱动层作用解析)
- IP地址和MAC地址的区分
- MD5和UUID
- C++ 输入cin
- 电子书《我的架构思想》小述
- AndroidStudio项目用Git上传码云出问题
- MVC设计模式