﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-小明思考-随笔分类-分布式计算</title><link>http://www.blogjava.net/sandy/category/51018.html</link><description>Just a software engineer</description><language>zh-cn</language><lastBuildDate>Thu, 22 Mar 2012 10:38:22 GMT</lastBuildDate><pubDate>Thu, 22 Mar 2012 10:38:22 GMT</pubDate><ttl>60</ttl><item><title>leveldb性能分析 - 随机写</title><link>http://www.blogjava.net/sandy/archive/2012/03/22/leveldb_benchmark.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Thu, 22 Mar 2012 09:32:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/22/leveldb_benchmark.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/372481.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/22/leveldb_benchmark.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/372481.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/372481.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 准备工作：1. 下载Snappy库Download source code from: http://code.google.com/p/snappy编译并安装./configure &amp; make &amp; sudo make install2. 编译leveldb自带的db_benchmake db_bench注意:在ubuntu 11.04上编译会出错，修改makefile:$(CX...&nbsp;&nbsp;<a href='http://www.blogjava.net/sandy/archive/2012/03/22/leveldb_benchmark.html'>阅读全文</a><img src ="http://www.blogjava.net/sandy/aggbug/372481.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-22 17:32 <a href="http://www.blogjava.net/sandy/archive/2012/03/22/leveldb_benchmark.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究11- 流程分析：读数据</title><link>http://www.blogjava.net/sandy/archive/2012/03/21/leveldb11.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Wed, 21 Mar 2012 09:30:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/21/leveldb11.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/372372.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/21/leveldb11.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/372372.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/372372.html</trackback:ping><description><![CDATA[leveldb读数据<br /><br />先看看ReadOptions有哪些参数可以指定：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Options&nbsp;that&nbsp;control&nbsp;read&nbsp;operations</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;ReadOptions&nbsp;{<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;是否检查checksum<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Default:&nbsp;false</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;verify_checksums;<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;是否将此次结果放入cache<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Default:&nbsp;true</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;fill_cache;<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">是否指定snapshot,否则读取当前版本<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Default:&nbsp;NULL</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Snapshot</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;snapshot;<br /><br />&nbsp;&nbsp;ReadOptions()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;verify_checksums(</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fill_cache(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;snapshot(NULL)&nbsp;{<br />&nbsp;&nbsp;}<br />};</span></div><br />下面看看读取的详细过程：<br />查询memtable=&gt;查询previous memtable(imm_)=&gt;查询文件(缓冲）<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Status&nbsp;DBImpl::Get(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ReadOptions</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;options,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;value)&nbsp;{<br />&nbsp;&nbsp;Status&nbsp;s;<br />&nbsp;&nbsp;MutexLock&nbsp;l(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">mutex_);<br />&nbsp;&nbsp;SequenceNumber&nbsp;snapshot;<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">设置snapshot</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(options.snapshot&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;snapshot&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;reinterpret_cast</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;SnapshotImpl</span><span style="color: #000000; ">*&gt;</span><span style="color: #000000; ">(options.snapshot)</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">number_;<br />&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;snapshot&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">LastSequence();<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;MemTable</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;mem&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;mem_;<br />&nbsp;&nbsp;MemTable</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;imm&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;imm_;<br />&nbsp;&nbsp;Version</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;current&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">current();<br />&nbsp;&nbsp;mem</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Ref();<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(imm&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;imm</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Ref();<br />&nbsp;&nbsp;current</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Ref();<br /><br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;have_stat_update&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;Version::GetStats&nbsp;stats;<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Unlock&nbsp;while&nbsp;reading&nbsp;from&nbsp;files&nbsp;and&nbsp;memtables</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;mutex_.Unlock();<br />&nbsp;&nbsp;&nbsp;&nbsp;LookupKey&nbsp;lkey(key,&nbsp;snapshot);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">先查询memtable</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(mem</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Get(lkey,&nbsp;value,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">s))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Done</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(imm&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;imm</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Get(lkey,&nbsp;value,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">s))&nbsp;{&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">然后查询previous&nbsp;memtable:imm_<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Done</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">从文件中读取</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;current</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Get(options,&nbsp;lkey,&nbsp;value,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">stats);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;have_stat_update&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;mutex_.Lock();<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000;">是否有文件需要被compaction,参见allowed_seek</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(have_stat_update&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;current</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">UpdateStats(stats))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;MaybeScheduleCompaction();<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;mem</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Unref();<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(imm&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;imm</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Unref();<br />&nbsp;&nbsp;current</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Unref();<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;s;<br />}</span></div><br /><br />重点来看看从version中读取：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Status&nbsp;Version::Get(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ReadOptions</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;options,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;LookupKey</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;k,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;value,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetStats</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;stats)&nbsp;{<br />&nbsp;&nbsp;Slice&nbsp;ikey&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;k.internal_key();<br />&nbsp;&nbsp;Slice&nbsp;user_key&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;k.user_key();<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Comparator</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;ucmp&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;vset_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">icmp_.user_comparator();<br />&nbsp;&nbsp;Status&nbsp;s;<br /><br />&nbsp;&nbsp;stats</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">seek_file&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;stats</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">seek_file_level&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;FileMetaData</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;last_file_read&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;last_file_read_level&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">从level0向高层查找，如果再低级level中查到，则不再查询</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;std::vector</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">FileMetaData</span><span style="color: #000000; ">*&gt;</span><span style="color: #000000; ">&nbsp;tmp;<br />&nbsp;&nbsp;FileMetaData</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;tmp2;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;level&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;config::kNumLevels;&nbsp;level</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;num_files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;files_[level].size();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">本层文件数为空，则返回</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(num_files&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #0000FF; ">continue</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Get&nbsp;the&nbsp;list&nbsp;of&nbsp;files&nbsp;to&nbsp;search&nbsp;in&nbsp;this&nbsp;level</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;FileMetaData</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">files_[level][</span><span style="color: #000000; ">0</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(level&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">level0特殊处理，因为key是重叠，所有符合条件的文件必须被查找</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp.reserve(num_files);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(uint32_t&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;num_files;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileMetaData</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;f&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;files[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(ucmp</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Compare(user_key,&nbsp;f</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">smallest.user_key())&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ucmp</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Compare(user_key,&nbsp;f</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">largest.user_key())&nbsp;</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp.push_back(f);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(tmp.empty())&nbsp;</span><span style="color: #0000FF; ">continue</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::sort(tmp.begin(),&nbsp;tmp.end(),&nbsp;NewestFirst);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">tmp[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;tmp.size();<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;二分法查找，某个key只可能属于一个文件</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uint32_t&nbsp;index&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;FindFile(vset_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">icmp_,&nbsp;files_[level],&nbsp;ikey);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">没有查到</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(index&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;num_files)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;files[index];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(ucmp</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Compare(user_key,&nbsp;tmp2</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">smallest.user_key())&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;All&nbsp;of&nbsp;"tmp2"&nbsp;is&nbsp;past&nbsp;any&nbsp;data&nbsp;for&nbsp;user_key</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">tmp2;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num_files&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(uint32_t&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;num_files;&nbsp;</span><span style="color: #000000; ">++</span><span style="color: #000000; ">i)&nbsp;{&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">遍历本层符合条件的文件</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(last_file_read&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;stats</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">seek_file&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">seek_file只记录第一个</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stats</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">seek_file&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;last_file_read;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stats</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">seek_file_level&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;last_file_read_level;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileMetaData</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;f&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;files[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last_file_read&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;f;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last_file_read_level&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;level;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">从table&nbsp;cache中读取</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;iter&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;vset_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">table_cache_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NewIterator(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">number,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">file_size);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iter</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Seek(ikey);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;done&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;GetValue(ucmp,&nbsp;iter,&nbsp;user_key,&nbsp;value,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">s);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">iter</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">status().ok())&nbsp;{&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">查找到</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;iter</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">status();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;iter;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;iter;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(done)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;Status::NotFound(Slice());&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Use&nbsp;an&nbsp;empty&nbsp;error&nbsp;message&nbsp;for&nbsp;speed</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">}</span></div><br />继续跟踪：TableCache<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #000000; ">Iterator</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;TableCache::NewIterator(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ReadOptions</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;options,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uint64_t&nbsp;file_number,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uint64_t&nbsp;file_size,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Table</span><span style="color: #000000; ">**</span><span style="color: #000000; ">&nbsp;tableptr)&nbsp;{<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(tableptr&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">tableptr&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">&nbsp;buf[</span><span style="color: #0000FF; ">sizeof</span><span style="color: #000000; ">(file_number)];<br />&nbsp;&nbsp;EncodeFixed64(buf,&nbsp;file_number);<br />&nbsp;&nbsp;Slice&nbsp;key(buf,&nbsp;</span><span style="color: #0000FF; ">sizeof</span><span style="color: #000000; ">(buf));<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">从LRU&nbsp;cache中查找</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;Cache::Handle</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;handle&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;cache_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Lookup(key);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(handle&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">加载文件<br />&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;fname&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;TableFileName(dbname_,&nbsp;file_number);<br />&nbsp;&nbsp;&nbsp;&nbsp;RandomAccessFile</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;file&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;Table</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;table&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;Status&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;env_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NewRandomAccessFile(fname,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">file);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(s.ok())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Table::Open(</span><span style="color: #000000; ">*</span><span style="color: #000000; ">options_,&nbsp;file,&nbsp;file_size,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">table);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">s.ok())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assert(table&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;NULL);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;file;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;We&nbsp;do&nbsp;not&nbsp;cache&nbsp;error&nbsp;results&nbsp;so&nbsp;that&nbsp;if&nbsp;the&nbsp;error&nbsp;is&nbsp;transient,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;or&nbsp;somebody&nbsp;repairs&nbsp;the&nbsp;file,&nbsp;we&nbsp;recover&nbsp;automatically.</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;NewErrorIterator(s);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">插入Cache</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;TableAndFile</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;tf&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;TableAndFile;<br />&nbsp;&nbsp;&nbsp;&nbsp;tf</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">file&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;file;<br />&nbsp;&nbsp;&nbsp;&nbsp;tf</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">table&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;table;<br />&nbsp;&nbsp;&nbsp;&nbsp;handle&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;cache_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Insert(key,&nbsp;tf,&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">DeleteEntry);<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;Table</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;table&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;reinterpret_cast</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">TableAndFile</span><span style="color: #000000; ">*&gt;</span><span style="color: #000000; ">(cache_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Value(handle))</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">table;<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">从Table对象中生成iterator</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;Iterator</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;result&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;table</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NewIterator(options);<br />&nbsp;&nbsp;result</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">RegisterCleanup(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">UnrefEntry,&nbsp;cache_,&nbsp;handle);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(tableptr&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">tableptr&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;table;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;result;<br />}</span></div><br /><br /><img src ="http://www.blogjava.net/sandy/aggbug/372372.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-21 17:30 <a href="http://www.blogjava.net/sandy/archive/2012/03/21/leveldb11.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究10- 流程分析：写数据</title><link>http://www.blogjava.net/sandy/archive/2012/03/21/leveldb10.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Wed, 21 Mar 2012 06:41:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/21/leveldb10.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/372345.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/21/leveldb10.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/372345.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/372345.html</trackback:ping><description><![CDATA[总体来说,leveldb的写操作有两个步骤，首先是针对log的append操作，然后是对memtable的插入操作。<br /><br />影响写性能的因素有：<br />1.<span style="color: #000000; "> write_buffer_size</span><br />2.<span style="color: #000000; "> kL0_SlowdownWritesTrigger</span> and<span style="color: #000000; "> kL0_StopWritesTrigger</span>.提高这两个值，能够增加写的性能，但是降低读的性能<br /><br />看看WriteOptions有哪些参数可以指定<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;WriteOptions&nbsp;{<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">设置sync=true,leveldb会调用fsync()，这会降低插入性能<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">同时会增加数据的安全性&nbsp;<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">Default:&nbsp;false</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;sync;<br /><br />&nbsp;&nbsp;WriteOptions()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;sync(</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;}<br />};</span></div><br /><br />首先把Key,value转成WriteBatch<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Status&nbsp;DB::Put(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;WriteOptions</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;opt,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;value)&nbsp;{<br />&nbsp;&nbsp;WriteBatch&nbsp;batch;<br />&nbsp;&nbsp;batch.Put(key,&nbsp;value);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;Write(opt,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">batch);<br />}</span></div><br />接下来就是真正的插入了<br />这里使用了两把锁，主要是想提高并发能力，减少上锁的时间。<br />首先是检查是否可写，然后append log，最后是插入memtable<br />&lt;db/dbimpl.cc&gt;<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Status&nbsp;DBImpl::Write(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;WriteOptions</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;options,&nbsp;WriteBatch</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;updates)&nbsp;{<br />&nbsp;&nbsp;Status&nbsp;status;<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">加锁</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;MutexLock&nbsp;l(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">mutex_);<br />&nbsp;&nbsp;LoggerId&nbsp;self;<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">拿到写log的权利</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;AcquireLoggingResponsibility(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">self);<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">检查是否可写</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;MakeRoomForWrite(</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">);&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;May&nbsp;temporarily&nbsp;release&nbsp;lock&nbsp;and&nbsp;wait</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;uint64_t&nbsp;last_sequence&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">LastSequence();<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(status.ok())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;WriteBatchInternal::SetSequence(updates,&nbsp;last_sequence&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;last_sequence&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;WriteBatchInternal::Count(updates);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Add&nbsp;to&nbsp;log&nbsp;and&nbsp;apply&nbsp;to&nbsp;memtable.&nbsp;&nbsp;We&nbsp;can&nbsp;release&nbsp;the&nbsp;lock&nbsp;during<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;this&nbsp;phase&nbsp;since&nbsp;the&nbsp;"logger_"&nbsp;flag&nbsp;protects&nbsp;against&nbsp;concurrent<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;loggers&nbsp;and&nbsp;concurrent&nbsp;writes&nbsp;into&nbsp;mem_.</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assert(logger_&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">self);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex_.Unlock();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">IO操作：写入LOG</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;log_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">AddRecord(WriteBatchInternal::Contents(updates));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(status.ok()&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;options.sync)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;logfile_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Sync();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">插入memtable</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(status.ok())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;WriteBatchInternal::InsertInto(updates,&nbsp;mem_);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex_.Lock();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assert(logger_&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">self);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">设置新的seqence&nbsp;number</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">SetLastSequence(last_sequence);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">释放写LOG锁</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;ReleaseLoggingResponsibility(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">self);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;status;<br />}</span></div><br />写流量控制：<br />&lt;db/dbimpl.cc&gt;<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Status&nbsp;DBImpl::MakeRoomForWrite(</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;force)&nbsp;{<br />&nbsp;&nbsp;mutex_.AssertHeld();<br />&nbsp;&nbsp;assert(logger_&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;allow_delay&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">!</span><span style="color: #000000; ">force;<br />&nbsp;&nbsp;Status&nbsp;s;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">bg_error_.ok())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Yield&nbsp;previous&nbsp;error</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;bg_error_;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">break</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow_delay&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NumLevelFiles(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;config::kL0_SlowdownWritesTrigger)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex_.Unlock();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">如果level0的文件大于kL0_SlowdownWritesTrigger阈值，则sleep&nbsp;1s，这样给compaction更多的CPU</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">SleepForMicroseconds(</span><span style="color: #000000; ">1000</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow_delay&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Do&nbsp;not&nbsp;delay&nbsp;a&nbsp;single&nbsp;write&nbsp;more&nbsp;than&nbsp;once</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mutex_.Lock();<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">force&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(mem_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">ApproximateMemoryUsage()&nbsp;</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">&nbsp;options_.write_buffer_size))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">可写</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">break</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(imm_&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;imm_:之前的memtable&nbsp;没有被compaction，需要等待</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bg_cv_.Wait();<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NumLevelFiles(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;config::kL0_StopWritesTrigger)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;level0文件个数大于kL0_StopWritesTrigger,需要等待</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log(options_.info_log,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">waiting<img src="http://www.blogjava.net/Images/dot.gif" alt="" />\n</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bg_cv_.Wait();<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">生成新的额memtable和logfile，把当前memtable传给imm_</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assert(versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">PrevLogNumber()&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uint64_t&nbsp;new_log_number&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NewFileNumber();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WritableFile</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;lfile&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;env_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NewWritableFile(LogFileName(dbname_,&nbsp;new_log_number),&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">lfile);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">s.ok())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">break</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;log_;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;logfile_;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logfile_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;lfile;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logfile_number_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;new_log_number;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;log::Writer(lfile);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imm_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;mem_;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;has_imm_.Release_Store(imm_);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mem_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;MemTable(internal_comparator_);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mem_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Ref();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;force&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Do&nbsp;not&nbsp;force&nbsp;another&nbsp;compaction&nbsp;if&nbsp;have&nbsp;room</span><span style="color: #008000; "><br /><div><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000; "> 发起compaction,dump imm_<br /></span></div></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MaybeScheduleCompaction();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000;">&nbsp;s;<br />}</span></div><br /><img src ="http://www.blogjava.net/sandy/aggbug/372345.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-21 14:41 <a href="http://www.blogjava.net/sandy/archive/2012/03/21/leveldb10.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究9- 流程分析：打开数据库</title><link>http://www.blogjava.net/sandy/archive/2012/03/20/leveldb9.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Tue, 20 Mar 2012 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/20/leveldb9.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/372251.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/20/leveldb9.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/372251.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/372251.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: leveldb 是通过Open函数来打开/新建数据库。Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->static&nbsp;Status&nbsp;Open(const&nbsp;Options&amp;&nbsp;options,&nbsp;&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/sandy/archive/2012/03/20/leveldb9.html'>阅读全文</a><img src ="http://www.blogjava.net/sandy/aggbug/372251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-20 16:02 <a href="http://www.blogjava.net/sandy/archive/2012/03/20/leveldb9.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究8- 内存中的数据结构Memtable/SkipList</title><link>http://www.blogjava.net/sandy/archive/2012/03/19/leveldb8.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Mon, 19 Mar 2012 08:31:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/19/leveldb8.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/372177.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/19/leveldb8.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/372177.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/372177.html</trackback:ping><description><![CDATA[我们知道,leveldb在写数据的时候，除了log文件，都要在内存中写一份。<br /><br />先看看SkipList【跳表】这个数据结构：<br /><img alt="" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/86/Skip_list.svg/470px-Skip_list.svg.png" /><br /><br />SkipList有如下特点：<br />1. 本质上一个排序好的链表<br />2. 分层，上层节点比下层的少，更具有跳跃性<br />3. 查询的复杂度是O(logn)<br /><br />SkipList跟红黑树等还是比较容易实现和理解的，主要长处是比较容易实现Lock free和遍历。<br />我们来看看leveldb的实现<br />插入：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">插入一个新的key</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename&nbsp;Key,&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Comparator</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;SkipList</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Key,Comparator</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::Insert(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Key</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key)&nbsp;{<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">查找插入节点,prev为各层的前置节点</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;Node</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;prev[kMaxHeight];<br />&nbsp;&nbsp;Node</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;x&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;FindGreaterOrEqual(key,&nbsp;prev);<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Our&nbsp;data&nbsp;structure&nbsp;does&nbsp;not&nbsp;allow&nbsp;duplicate&nbsp;insertion</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;assert(x&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;NULL&nbsp;</span><span style="color: #000000; ">||</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">!</span><span style="color: #000000; ">Equal(key,&nbsp;x</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">key));<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">生成随机高度</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;height&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;RandomHeight();<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(height&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;GetMaxHeight())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;GetMaxHeight();&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;height;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev[i]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;head_;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">设置当前最大高度</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;max_height_.NoBarrier_Store(reinterpret_cast</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">*&gt;</span><span style="color: #000000; ">(height));<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">生成新节点</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NewNode(key,&nbsp;height);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;height;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">设置新节点的各层的下一跳</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;x</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NoBarrier_SetNext(i,&nbsp;prev[i]</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">NoBarrier_Next(i));<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">设置前节点的next为当前节点，完成插入</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;prev[i]</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">SetNext(i,&nbsp;x);<br />&nbsp;&nbsp;}<br />}</span></div><br />查询：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename&nbsp;Key,&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Comparator</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />typename&nbsp;SkipList</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Key,Comparator</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::Node</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;SkipList</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Key,Comparator</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::FindGreaterOrEqual(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Key</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key,&nbsp;Node</span><span style="color: #000000; ">**</span><span style="color: #000000; ">&nbsp;prev)<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;Node</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;x&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;head_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;GetMaxHeight()&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">从高层开始查找，依次到0&nbsp;level</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;Node</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;next&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;x</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Next(level);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(KeyIsAfterNode(key,&nbsp;next))&nbsp;{&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">比next&nbsp;key&nbsp;要大<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Keep&nbsp;searching&nbsp;in&nbsp;this&nbsp;list</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">比next&nbsp;key小，查找下一层<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">标记当前level的前置节点</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(prev&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL)&nbsp;prev[level]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;x;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(level&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;level</span><span style="color: #000000; ">--</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />}<br /><br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">typename&nbsp;Key,&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Comparator</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;SkipList</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Key,Comparator</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::Contains(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Key</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key)&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;Node</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;x&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;FindGreaterOrEqual(key,&nbsp;NULL);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(x&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;NULL&nbsp;</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">&nbsp;Equal(key,&nbsp;x</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">key))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;}<br />}</span></div><br /><br />接着我们看看leveldb MemTable的实现，很简单了，基本是对SkipList访问一个封装<br />&lt;db/memtable.h&gt;<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;MemTable&nbsp;{<br />&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">explicit</span><span style="color: #000000; ">&nbsp;MemTable(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKeyComparator</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;comparator);<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">增加引用计数</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Ref()&nbsp;{&nbsp;</span><span style="color: #000000; ">++</span><span style="color: #000000; ">refs_;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">减少引用计数</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Unref()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">--</span><span style="color: #000000; ">refs_;<br />&nbsp;&nbsp;&nbsp;&nbsp;assert(refs_&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(refs_&nbsp;</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">内存使用量</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;size_t&nbsp;ApproximateMemoryUsage();<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">遍历操作</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;Iterator</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;NewIterator();<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">插入</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Add(SequenceNumber&nbsp;seq,&nbsp;ValueType&nbsp;type,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;value);<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">查询</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;Get(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;LookupKey</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key,&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;value,&nbsp;Status</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;s);<br /><br />&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">MemTable();&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Private&nbsp;since&nbsp;only&nbsp;Unref()&nbsp;should&nbsp;be&nbsp;used&nbsp;to&nbsp;delete&nbsp;it<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">key&nbsp;compartor，用于排序</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;KeyComparator&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKeyComparator&nbsp;comparator;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">explicit</span><span style="color: #000000; ">&nbsp;KeyComparator(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKeyComparator</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;c)&nbsp;:&nbsp;comparator(c)&nbsp;{&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">()(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;a,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;b)&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;};<br />&nbsp;&nbsp;friend&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;MemTableIterator;<br />&nbsp;&nbsp;friend&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;MemTableBackwardIterator;<br /><br />&nbsp;&nbsp;typedef&nbsp;SkipList</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">,&nbsp;KeyComparator</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;Table;<br /><br />&nbsp;&nbsp;KeyComparator&nbsp;comparator_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;refs_;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">引用计数</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;Arena&nbsp;arena_;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">内存分配器</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;Table&nbsp;table_;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">数据存放SkipList<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;No&nbsp;copying&nbsp;allowed</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;MemTable(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;MemTable</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;MemTable</span><span style="color: #000000; ">&amp;</span><span style="color: #000000;">);<br />};</span></div><br />先看看插入<br />&lt;db/memtable.cc&gt;<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;MemTable::Add(SequenceNumber&nbsp;s,&nbsp;ValueType&nbsp;type,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;value)&nbsp;{<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">数据结构：<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">1.internal&nbsp;key&nbsp;size&nbsp;:&nbsp;Varint32&nbsp;(length&nbsp;of&nbsp;2+3)<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">2.key&nbsp;data<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">3.SequenceNumber+Key&nbsp;type:&nbsp;8&nbsp;bytes<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">4&nbsp;value&nbsp;size:&nbsp;Varint32<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">5&nbsp;value&nbsp;data</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;size_t&nbsp;key_size&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;key.size();<br />&nbsp;&nbsp;size_t&nbsp;val_size&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;value.size();<br />&nbsp;&nbsp;size_t&nbsp;internal_key_size&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;key_size&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;size_t&nbsp;encoded_len&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VarintLength(internal_key_size)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;internal_key_size&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VarintLength(val_size)&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;val_size;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;buf&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;arena_.Allocate(encoded_len);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;p&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;EncodeVarint32(buf,&nbsp;internal_key_size);<br />&nbsp;&nbsp;memcpy(p,&nbsp;key.data(),&nbsp;key_size);<br />&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;key_size;<br />&nbsp;&nbsp;EncodeFixed64(p,&nbsp;(s&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">|</span><span style="color: #000000; ">&nbsp;type);<br />&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;EncodeVarint32(p,&nbsp;val_size);<br />&nbsp;&nbsp;memcpy(p,&nbsp;value.data(),&nbsp;val_size);<br />&nbsp;&nbsp;assert((p&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;val_size)&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;buf&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;encoded_len);<br />&nbsp;&nbsp;table_.Insert(buf);<br />}</span></div><br />查询<br />&lt;db/memtable.cc&gt;<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;MemTable::Get(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;LookupKey</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key,&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;value,&nbsp;Status</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;s)&nbsp;{<br />&nbsp;&nbsp;Slice&nbsp;memkey&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;key.memtable_key();<br />&nbsp;&nbsp;Table::Iterator&nbsp;iter(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">table_);<br />&nbsp;&nbsp;iter.Seek(memkey.data());<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(iter.Valid())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;entry&nbsp;format&nbsp;is:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;klength&nbsp;&nbsp;varint32<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;userkey&nbsp;&nbsp;char[klength]<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;tag&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uint64<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;vlength&nbsp;&nbsp;varint32<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;&nbsp;&nbsp;&nbsp;char[vlength]<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Check&nbsp;that&nbsp;it&nbsp;belongs&nbsp;to&nbsp;same&nbsp;user&nbsp;key.&nbsp;&nbsp;We&nbsp;do&nbsp;not&nbsp;check&nbsp;the<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;sequence&nbsp;number&nbsp;since&nbsp;the&nbsp;Seek()&nbsp;call&nbsp;above&nbsp;should&nbsp;have&nbsp;skipped<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;all&nbsp;entries&nbsp;with&nbsp;overly&nbsp;large&nbsp;sequence&nbsp;numbers.</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;entry&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;iter.key();<br />&nbsp;&nbsp;&nbsp;&nbsp;uint32_t&nbsp;key_length;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;key_ptr&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;GetVarint32Ptr(entry,&nbsp;entry</span><span style="color: #000000; ">+</span><span style="color: #000000; ">5</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">key_length);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(comparator_.comparator.user_comparator()</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Compare(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Slice(key_ptr,&nbsp;key_length&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key.user_key())&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Correct&nbsp;user&nbsp;key</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;uint64_t&nbsp;tag&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;DecodeFixed64(key_ptr&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;key_length&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">8</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">switch</span><span style="color: #000000; ">&nbsp;(static_cast</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">ValueType</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(tag&nbsp;</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0xff</span><span style="color: #000000; ">))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;kTypeValue:&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Slice&nbsp;v&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;GetLengthPrefixedSlice(key_ptr&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;key_length);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">assign(v.data(),&nbsp;v.size());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">case</span><span style="color: #000000; ">&nbsp;kTypeDeletion:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Status::NotFound(Slice());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;<br />}</span></div><img src ="http://www.blogjava.net/sandy/aggbug/372177.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-19 16:31 <a href="http://www.blogjava.net/sandy/archive/2012/03/19/leveldb8.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究7-Version/VersionSet/VersionEdit</title><link>http://www.blogjava.net/sandy/archive/2012/03/16/leveldb7.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Fri, 16 Mar 2012 09:10:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/16/leveldb7.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/372028.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/16/leveldb7.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/372028.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/372028.html</trackback:ping><description><![CDATA[leveldb 使用 version 来保存数据库的状态。<br />
<br />
先看看一个重要的数据结果，sst file的META info<br />
&lt;db/version_edit.h&gt;<br />
<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;FileMetaData&nbsp;{<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;refs;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">引用计数</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;allowed_seeks;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">允许的seeks次数</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;uint64_t&nbsp;number;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">文件编号</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;uint64_t&nbsp;file_size;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">文件大小</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;InternalKey&nbsp;smallest;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">最小的key</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;InternalKey&nbsp;largest;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">最大的key&nbsp;</span><span style="color: #008000; "><br />
</span><span style="color: #000000; "><br />
&nbsp;&nbsp;FileMetaData()&nbsp;:&nbsp;refs(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">),&nbsp;allowed_seeks(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">30</span><span style="color: #000000; ">),&nbsp;file_size(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;{&nbsp;}<br />
};</span></div>
<br />
这里面有一个很有意思的字段: allowed_seeks,代表了可以seek的次数，为0的时候表示这个文件需要被compaction.如何设置seeks次数呢？文件大小除以16k，不到100算100。<br />
<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">allowed_seeks&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(f</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">file_size&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">16384</span><span style="color: #000000; ">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(f</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">allowed_seeks&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">100</span><span style="color: #000000; ">)&nbsp;f</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">allowed_seeks&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">100</span><span style="color: #000000; ">;</span></div>
<br />
原因，请看leveldb的注释：<br />
<br />
<div>// We arrange to automatically compact this file after a certain number of seeks.&nbsp; Let's assume:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; (1) One seek costs 10ms<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; (2) Writing or reading 1MB costs 10ms (100MB/s)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; (3) A compaction of 1MB does 25MB of IO:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1MB read from this level<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10-12MB read from next level (boundaries may be misaligned)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10-12MB written to next level<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // This implies that 25 seeks cost the same as the compaction<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // of 1MB of data.&nbsp; I.e., one seek costs approximately the<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // same as the compaction of 40KB of data.&nbsp; We are a little<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // conservative and allow approximately one seek for every 16KB<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // of data before triggering a compaction.</div>
<br />
<br />
接下来看Version的定义，version其实就是一系列的SST file的集合。<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Version&nbsp;{<br />
&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">生成iterator用于遍历</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;AddIterators(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ReadOptions</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">,&nbsp;std::vector</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Iterator</span><span style="color: #000000; ">*&gt;*</span><span style="color: #000000; ">&nbsp;iters);<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">根据key来查询，若没有查到，更新GetStats</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">struct</span><span style="color: #000000; ">&nbsp;GetStats&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;FileMetaData</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;seek_file;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;seek_file_level;<br />
&nbsp;&nbsp;};<br />
&nbsp;&nbsp;Status&nbsp;Get(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ReadOptions</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;LookupKey</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key,&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;val,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetStats</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;stats);<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">是否需要进行compaction</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;UpdateStats(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;GetStats</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;stats);<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">引用计算，避免在被引用时候删除</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Ref();<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Unref();<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">查询和key&nbsp;range有关的files</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;GetOverlappingInputs(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKey</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;begin,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;NULL&nbsp;means&nbsp;before&nbsp;all&nbsp;keys</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKey</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;end,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;NULL&nbsp;means&nbsp;after&nbsp;all&nbsp;keys</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::vector</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">FileMetaData</span><span style="color: #000000; ">*&gt;*</span><span style="color: #000000; ">&nbsp;inputs);<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">计算是否level对某个key&nbsp;range是否有overlap</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;OverlapInLevel(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;smallest_user_key,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;largest_user_key);<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">memtable&nbsp;output应该放到哪个level</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;PickLevelForMemTableOutput(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;smallest_user_key,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;largest_user_key);<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">某个level的文件个数</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;NumFiles(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level)&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;{&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;files_[level].size();&nbsp;}<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Return&nbsp;a&nbsp;human&nbsp;readable&nbsp;string&nbsp;that&nbsp;describes&nbsp;this&nbsp;version's&nbsp;contents.</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;DebugString()&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">;<br />
<br />
&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />
&nbsp;&nbsp;friend&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Compaction;<br />
&nbsp;&nbsp;friend&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;VersionSet;<br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;LevelFileNumIterator;<br />
&nbsp;&nbsp;Iterator</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;NewConcatenatingIterator(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;ReadOptions</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level)&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">;<br />
<br />
&nbsp;&nbsp;VersionSet</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;vset_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;VersionSet&nbsp;to&nbsp;which&nbsp;this&nbsp;Version&nbsp;belongs</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;Version</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;next_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Next&nbsp;version&nbsp;in&nbsp;linked&nbsp;list</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;Version</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;prev_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Previous&nbsp;version&nbsp;in&nbsp;linked&nbsp;list</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;refs_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Number&nbsp;of&nbsp;live&nbsp;refs&nbsp;to&nbsp;this&nbsp;version<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">sst&nbsp;files&nbsp;</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;std::vector</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">FileMetaData</span><span style="color: #000000; ">*&gt;</span><span style="color: #000000; ">&nbsp;files_[config::kNumLevels];<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">下一个要被compaction的文件</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;FileMetaData</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;file_to_compact_;<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;file_to_compact_level_;<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">compaction&nbsp;score:&gt;1表示要compaction</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;compaction_score_;<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;compaction_level_;<br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">explicit</span><span style="color: #000000; ">&nbsp;Version(VersionSet</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;vset)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;vset_(vset),&nbsp;next_(</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">),&nbsp;prev_(</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">),&nbsp;refs_(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file_to_compact_(NULL),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file_to_compact_level_(</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;compaction_score_(</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;compaction_level_(</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)&nbsp;{<br />
&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">Version();<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;No&nbsp;copying&nbsp;allowed</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;Version(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Version</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">);<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">operator</span><span style="color: #000000; ">=</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Version</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">);<br />
};<br />
</span></div><br /><br />那VersionSet呢？VersionSet 是version组成一个双向循环链表。<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;VersionSet{<br /></span><span style="color: #008000; ">//</span><span style="color: #008000; ">.&nbsp;.&nbsp;.</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">Env</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;env_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;dbname_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Options</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;options_;<br />&nbsp;&nbsp;TableCache</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;table_cache_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKeyComparator&nbsp;icmp_;<br />&nbsp;&nbsp;uint64_t&nbsp;next_file_number_;<br />&nbsp;&nbsp;uint64_t&nbsp;manifest_file_number_;<br />&nbsp;&nbsp;uint64_t&nbsp;last_sequence_;<br />&nbsp;&nbsp;uint64_t&nbsp;log_number_;<br /><br />&nbsp;&nbsp;WritableFile</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;descriptor_file_;<br />&nbsp;&nbsp;log::Writer</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;descriptor_log_;<br />&nbsp;&nbsp;Version&nbsp;dummy_versions_;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Head&nbsp;of&nbsp;circular&nbsp;doubly-linked&nbsp;list&nbsp;of&nbsp;versions.</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;Version</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;current_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;==&nbsp;dummy_versions_.prev_<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">每层都有一个compact&nbsp;pointer用于指示下次从哪里开始compact,以用于实现循环compact</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;compact_pointer_[config::kNumLevels];<br /></span><span style="color: #008000; ">//</span><span style="color: #008000; ">.&nbsp;.&nbsp;.</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">}</span></div><br /><br />VersionEdit是version对象的变更记录，用于写入manifest.这样通过原始的version加上一系列的versionedit的记录，就可以恢复到最新状态。<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;VersionEdit&nbsp;{<br />&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;VersionEdit()&nbsp;{&nbsp;Clear();&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">VersionEdit()&nbsp;{&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;Clear();<br /><br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;SetComparatorName(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;name)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;has_comparator_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;comparator_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;name.ToString();<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;SetLogNumber(uint64_t&nbsp;num)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;has_log_number_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;log_number_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;num;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;SetPrevLogNumber(uint64_t&nbsp;num)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;has_prev_log_number_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;prev_log_number_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;num;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;SetNextFile(uint64_t&nbsp;num)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;has_next_file_number_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;next_file_number_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;num;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;SetLastSequence(SequenceNumber&nbsp;seq)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;has_last_sequence_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;last_sequence_&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;seq;<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;SetCompactPointer(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKey</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;key)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;compact_pointers_.push_back(std::make_pair(level,&nbsp;key));<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">添加meta&nbsp;file</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;AddFile(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level,&nbsp;uint64_t&nbsp;file,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uint64_t&nbsp;file_size,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKey</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;smallest,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;InternalKey</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;largest)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;FileMetaData&nbsp;f;<br />&nbsp;&nbsp;&nbsp;&nbsp;f.number&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;file;<br />&nbsp;&nbsp;&nbsp;&nbsp;f.file_size&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;file_size;<br />&nbsp;&nbsp;&nbsp;&nbsp;f.smallest&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;smallest;<br />&nbsp;&nbsp;&nbsp;&nbsp;f.largest&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;largest;<br />&nbsp;&nbsp;&nbsp;&nbsp;new_files_.push_back(std::make_pair(level,&nbsp;f));<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">删除特定的文件</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;DeleteFile(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;level,&nbsp;uint64_t&nbsp;file)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;deleted_files_.insert(std::make_pair(level,&nbsp;file));<br />&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">编码，解码：用于写入manifest</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;EncodeTo(std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;dst)&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;Status&nbsp;DecodeFrom(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Slice</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;src);<br /><br />&nbsp;&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;DebugString()&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">;<br /><br />&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;friend&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;VersionSet;<br /><br />&nbsp;&nbsp;typedef&nbsp;std::</span><span style="color: #0000FF; ">set</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;std::pair</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">,&nbsp;uint64_t</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;DeletedFileSet;<br /><br />&nbsp;&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;comparator_;<br />&nbsp;&nbsp;uint64_t&nbsp;log_number_;<br />&nbsp;&nbsp;uint64_t&nbsp;prev_log_number_;<br />&nbsp;&nbsp;uint64_t&nbsp;next_file_number_;<br />&nbsp;&nbsp;SequenceNumber&nbsp;last_sequence_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;has_comparator_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;has_log_number_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;has_prev_log_number_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;has_next_file_number_;<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;has_last_sequence_;<br /><br />&nbsp;&nbsp;std::vector</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;std::pair</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">,&nbsp;InternalKey</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;compact_pointers_;<br />&nbsp;&nbsp;DeletedFileSet&nbsp;deleted_files_;<br />&nbsp;&nbsp;std::vector</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;std::pair</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">,&nbsp;FileMetaData</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;new_files_;<br />};</span></div><br /><br /><img src ="http://www.blogjava.net/sandy/aggbug/372028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-16 17:10 <a href="http://www.blogjava.net/sandy/archive/2012/03/16/leveldb7.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究6- Level和Compaction</title><link>http://www.blogjava.net/sandy/archive/2012/03/15/leveldb6.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Thu, 15 Mar 2012 09:28:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/15/leveldb6.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/371848.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/15/leveldb6.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/371848.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/371848.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: leveldb之所以使用level作为数据库名称，精华就在于level的设计。本质是一种归并排序算法。这样设计的好处主要是可以减少compaction的次数和每次的文件个数。Compaction为什么要compaction?&nbsp;compaction可以提高数据的查询效率，没有经过compaction，需要从很多SST file去查找，而做过compaction后，只需要从有限的SST文件去...&nbsp;&nbsp;<a href='http://www.blogjava.net/sandy/archive/2012/03/15/leveldb6.html'>阅读全文</a><img src ="http://www.blogjava.net/sandy/aggbug/371848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-15 17:28 <a href="http://www.blogjava.net/sandy/archive/2012/03/15/leveldb6.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究5- Snapshot</title><link>http://www.blogjava.net/sandy/archive/2012/03/13/leveldb5.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Tue, 13 Mar 2012 08:54:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/13/leveldb5.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/371812.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/13/leveldb5.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/371812.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/371812.html</trackback:ping><description><![CDATA[所谓snapshot就是一个快照，我们可以从快照中读到旧的数据。<br /><br />先写一个测试程序来看看snapshot的使用：<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />#include&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">leveldb/db.h</span><span style="color: #000000; ">"</span><span style="color: #000000; "><br /><br /></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;leveldb;<br /><br /><br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;DB&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">db&nbsp;;<br />&nbsp;&nbsp;&nbsp;&nbsp;Options&nbsp;op;<br />&nbsp;&nbsp;&nbsp;&nbsp;op.create_if_missing&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;Status&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;DB::Open(op,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">/tmp/testdb</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">db);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">create&nbsp;successfully</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Put(WriteOptions(),</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abcd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">1234</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">put&nbsp;successfully</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Get(ReadOptions(),</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abcd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">get&nbsp;successfully,value:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;value&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Snapshot&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;ss&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">GetSnapshot();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReadOptions&nbsp;rop;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Put(WriteOptions(),</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abcd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">123456</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Get(rop,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abcd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">get&nbsp;successfully,value:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;value&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rop.snapshot&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;ss;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Get(rop,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abcd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">get&nbsp;from&nbsp;snapshot&nbsp;successfully,value:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;value&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">ReleaseSnapshot(ss);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;db;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />}</span></div><br />程序运行的输出结果是：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">create&nbsp;successfully<br />put&nbsp;successfully<br /></span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&nbsp;successfully,value:</span><span style="color: #000000; ">1234</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&nbsp;successfully,value:</span><span style="color: #000000; ">123456</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">get</span><span style="color: #000000; ">&nbsp;from&nbsp;snapshot&nbsp;successfully,value:</span><span style="color: #000000; ">1234</span></div><br />可以看出，即使在数据更新后，我们仍然可以从snapshot中读到旧的数据。<br /><br />下面我们来分析leveldb中snapshot的实现。<br /><br />SequenceNumber(db/dbformat.h)<br /><div>SequenceNumber是leveldb很重要的东西，每次对数据库进行更新操作，都会生成一个新的SequenceNumber,64bits，其中高8位为0，可以跟key的类型(8bits)进行合并成64bits。</div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; "><div>typedef uint64_t SequenceNumber;<br /><br />// We leave eight bits empty at the bottom so a type and sequence#<br />// can be packed together into 64-bits.<br />static const SequenceNumber kMaxSequenceNumber =<br />&nbsp;&nbsp;&nbsp; ((0x1ull &lt;&lt; 56) - 1);</div></span></div><br />SnapShot(db/snapshot.h),，可以看出snapshot其实就是一个sequence number<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;SnapshotImpl&nbsp;:&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Snapshot&nbsp;{<br />&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">创建后保持不变</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;SequenceNumber&nbsp;number_;&nbsp;&nbsp;<br /><br />&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;friend&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;SnapshotList;&nbsp;<br /><br />&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">双向循环链表</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;SnapshotImpl</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;prev_;<br />&nbsp;&nbsp;SnapshotImpl</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;next_;<br /><br />&nbsp;&nbsp;SnapshotList</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;list_;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;just&nbsp;for&nbsp;sanity&nbsp;checks</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">};</span></div><br />创建snapshot:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Snapshot</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;DBImpl::GetSnapshot()&nbsp;{<br />&nbsp;&nbsp;MutexLock&nbsp;l(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">mutex_);<br />&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;snapshots_.New(versions_</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">LastSequence());<br />}</span></div><br />删除snapshot:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;DBImpl::ReleaseSnapshot(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Snapshot</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;s)&nbsp;{<br />&nbsp;&nbsp;MutexLock&nbsp;l(</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">mutex_);<br />&nbsp;&nbsp;snapshots_.Delete(reinterpret_cast</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;SnapshotImpl</span><span style="color: #000000; ">*&gt;</span><span style="color: #000000; ">(s));<br />}</span></div><br /><br /><br /><br /><img src ="http://www.blogjava.net/sandy/aggbug/371812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-13 16:54 <a href="http://www.blogjava.net/sandy/archive/2012/03/13/leveldb5.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究4- 数据文件的格式和生成</title><link>http://www.blogjava.net/sandy/archive/2012/03/12/leveldb4.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Mon, 12 Mar 2012 10:21:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/12/leveldb4.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/371712.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/12/leveldb4.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/371712.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/371712.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: leveldb使用SSTable格式来保存数据。格式为:(当前没有META BLOCK)SSTABLE = |DATA BLOCK1|DATA BLOCK2|...|DATA BLOCK N|META BLOCK1|...|META BLOCK N|META INDEX BLOCK|DATA INDEX BLOCK|Footer|DATA BLOCK = |KeyValues|Restart ar...&nbsp;&nbsp;<a href='http://www.blogjava.net/sandy/archive/2012/03/12/leveldb4.html'>阅读全文</a><img src ="http://www.blogjava.net/sandy/aggbug/371712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-12 18:21 <a href="http://www.blogjava.net/sandy/archive/2012/03/12/leveldb4.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究3-数据库日志文件格式</title><link>http://www.blogjava.net/sandy/archive/2012/03/09/leveldb3.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Fri, 09 Mar 2012 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/09/leveldb3.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/371582.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/09/leveldb3.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/371582.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/371582.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: leveldb在每次数据库操作之前都会把操作记录下来。主要实现在db\log_format.h,db\log_reader.h,db\log_reader.cc,db\log_write.h,db\log_write.cc中。我们来具体看看实现。日志格式db\log_format.hlog是分块的，每块为32K,每条记录的记录头为7个字节，前四个为CRC，然后是长度（2个字节）...&nbsp;&nbsp;<a href='http://www.blogjava.net/sandy/archive/2012/03/09/leveldb3.html'>阅读全文</a><img src ="http://www.blogjava.net/sandy/aggbug/371582.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-09 16:00 <a href="http://www.blogjava.net/sandy/archive/2012/03/09/leveldb3.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究2- 存储分析</title><link>http://www.blogjava.net/sandy/archive/2012/03/09/leveldb2.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Fri, 09 Mar 2012 03:44:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/09/leveldb2.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/371533.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/09/leveldb2.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/371533.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/371533.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 对于一个db来说，存储是至关重要的问题。运行上一篇的测试程序后，会发现leveldb会生成以下文件：SST文件：数据文件 -- sstable格式*.log: 数据库日志文件 -- 顺序记录所有数据库操作，用来恢复数据CURRENT: 文本文件，表明当面的manifest文件LOCK:空文件，数据库锁，防止多进程访问LOG: 日志文件，文本格式LOG.old:上一次的日志文件MANIFEST: 数...&nbsp;&nbsp;<a href='http://www.blogjava.net/sandy/archive/2012/03/09/leveldb2.html'>阅读全文</a><img src ="http://www.blogjava.net/sandy/aggbug/371533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-09 11:44 <a href="http://www.blogjava.net/sandy/archive/2012/03/09/leveldb2.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>leveldb研究 - 编译/调试</title><link>http://www.blogjava.net/sandy/archive/2012/03/08/leveldb1.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Thu, 08 Mar 2012 03:44:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/08/leveldb1.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/371423.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/08/leveldb1.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/371423.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/371423.html</trackback:ping><description><![CDATA[leveldb是 google对bigtable的一个简化版的开源实现，很有研究价值。<br /><br />我的编译环境:ubuntu 32&amp;g++ 4.6<br /><br />1.安装git并下载代码<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">sudo&nbsp;apt</span><span style="color: #000000; ">-</span><span style="color: #000000; ">get&nbsp;install&nbsp;git</span><span style="color: #000000; ">-</span><span style="color: #000000; ">core<br />git&nbsp;clone&nbsp;https:</span><span style="color: #008000; ">//</span><span style="color: #008000; ">code.google.com/p/leveldb/</span></div><br />2. 编译leveldb<br /><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #000000;">cd&nbsp;leveldb<br />.</span><span style="color: #000000; ">/</span><span style="color: #000000; ">build_detect_platform<br />make</span></div><br />为了能够调试，修改Makefile为debug mode(B模式)<br />OPT ?= -g2<br /><br />编译后会生成库文件：libleveldb.a<br /><br />3. 编写测试程序<br />ldbtest.cpp<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />#include&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">leveldb/db.h</span><span style="color: #000000; ">"</span><span style="color: #000000; "><br /><br /></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;leveldb;<br /><br /></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;DB&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">db&nbsp;;<br />&nbsp;&nbsp;&nbsp;&nbsp;Options&nbsp;op;<br />&nbsp;&nbsp;&nbsp;&nbsp;op.create_if_missing&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;Status&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;DB::Open(op,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">/tmp/testdb</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">db);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">create&nbsp;successfully</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Put(WriteOptions(),</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abcd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">1234</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">put&nbsp;successfully</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;db</span><span style="color: #000000; ">-&gt;</span><span style="color: #000000; ">Get(ReadOptions(),</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abcd</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(s.ok()){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">get&nbsp;successfully,value:</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;value&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">get&nbsp;failed</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">put&nbsp;failed</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">create&nbsp;failed</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">&nbsp;endl;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;db;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />}</span></div><div>注意link的时候需要加上-lpthread.<br /><br />运行后得到结果：(Eclipse中运行）<br /></div><div><img src="data:image/png;base64,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" alt="" /></div><br /><img src ="http://www.blogjava.net/sandy/aggbug/371423.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-08 11:44 <a href="http://www.blogjava.net/sandy/archive/2012/03/08/leveldb1.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Learn From HBase/Bigtable</title><link>http://www.blogjava.net/sandy/archive/2012/03/07/Learn_From_HBase.html</link><dc:creator>小明</dc:creator><author>小明</author><pubDate>Wed, 07 Mar 2012 02:42:00 GMT</pubDate><guid>http://www.blogjava.net/sandy/archive/2012/03/07/Learn_From_HBase.html</guid><wfw:comment>http://www.blogjava.net/sandy/comments/371379.html</wfw:comment><comments>http://www.blogjava.net/sandy/archive/2012/03/07/Learn_From_HBase.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/sandy/comments/commentRss/371379.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/sandy/services/trackbacks/371379.html</trackback:ping><description><![CDATA[<div><p>学习软件有三个境界，第一个境界是会使用它，第二个境界是懂得背后的原理，明白它的架构体系，第三个境界学习他的所长，为我所用。研究HBase/BigTable架构和源码一段时间后，我总结了一些东西可以供我们在设计分布式系统借鉴使用。</p><p><strong>1.&nbsp;使用可信任的分布式组件来搭建自己的分布式系统。</strong><br />  设 计一个可靠，健壮的分布式系统是比较困难的。我们知道，为了防止SPOF(Single Point Of  Failure)问题，我们要分散风险，把数据放在多个nodes上面去，但是这样带来了是数据的同步问题和版本问题，解决这个问题需要运用复杂的  Paxos协议，系统的复杂度自然就升高了。另外一个需要解决的问题是分布式锁和事件通知机制，以及全局信息共享，设计这些都需要大量的精力和仔细的研  究。</p><p>HBase就不用考虑这些问题，它把数据的同步和冗余问题交给了Hadoop,把锁机制和全局共享交给了Zookeeper,这大大简化了HBase的设计。</p><p>所以我们设计系统的时候，也要尽量利用这些可靠，稳定的组件。目前比较流行和稳定的有：<br /> 分布式文件系统&nbsp;-&nbsp;HDFS<br /> 分布式锁和目录&nbsp;-&nbsp;Zookeeper<br /> 缓存&nbsp;-&nbsp;MemCached<br /> 消息队列&nbsp;-&nbsp;ActiveMQ</p><p><strong>2.避免单点问题(SPOF)</strong><br /> 设计分布式系统要时刻考虑到失败，不单是软件可能失败，硬件也可能挂掉，所以我们系统里面就不能有不可替代的角色。</p><p>HBase  使用Master&nbsp;Server来监控所有的Region  Server,一旦其中的一台出现问题，在其上的Region将会被转移到其他的Region  Server，避免了服务中断。而Master&nbsp;Server也可以多台备选，一台挂掉之后，其他的备胎则会&#8221;继承遗志&#8220;，从而让整个系统得以生存。</p><p>那  HBase如何做到这个呢，一个是使用&#8221;心跳机制&#8221;，即Region  Server要主动定期向Master汇报状况，另外一个是利用zookeeper里面的&#8221;生命节点&#8220;，每个server在启动后要在ZK里面注册，一旦  这个server挂掉，它在ZK里面的节点就会消失，监听这个节点的server就会得到通知。</p><p><strong>3.利用不变性提高系统的吞吐量</strong><br /> 我们知道，很多进程/线程修改同一个东西的时候，我们就需要锁机制来避免冲突。但是锁带来的问题是系统性能下降。如果对于一个只读的对象，就不需要锁了。</p><p>HBase   在设计存储的时候考虑到这一点，最新的数据是放在memory里面，以提高性能。但是memory是有限的，我们不可能让数据一直放在memory里面，   所以我们需要定时把这些数据写到HDFS/磁盘上面。一种设计是写到一个可修改的大文件中去，这样对这个文件的读写就需要加锁了。HBase是每次都写到   一个新的文件中，一旦文件创建后，这个文件将不能被修改，就是所谓的create-one-read-many。当然这样也有一个问题，就是时间长了，会  有很多的小文件，每次查找，需要查找这所有的文件，降低了系统的性能，HBase会定时的合并这些小文件生成一个大文件。</p><p><strong>4.利用索引块提高文件的查询速度</strong><br /> HBase的存储文件(HFile)是用来存储很多排序后的Key-Value的，如何设计一种支持快速随机查询和压缩的文件是一个有意思的话题。</p><p>HFile  在文件的尾部增加了索引块，但是不可能对任何一个rowkey都做索引，这样的话索引块会很大，而且也不利于压缩。HFile的做法是定义一个Data   Block的大小，这样就把数据划分了一个一个的Block，索引只针对这些block做，Block是可以被压缩的。当查询一个rowkey的时候，如  果没有cache的话，首先使用二分法定位到具体的block，然后再解压，遍历查询具体的key。</p><p>HFile这样的设计兼顾了速度和文件大小的平衡。</p><p><strong>5.自定义RPC机制提供更大的灵活性</strong><br />  HBase/Hadoop  都没有利用标准的Java远程调用规范RMI,而是自己搞了一套。这样做的好处有几点，一是减少网络流量，我们知道，java RMI使用了java  serlizable来传递参数，java序列化有很多无关的类信息，都占用不少的空间，而且这会带来对java版本的依赖。二是带来更大的灵活性，你可  以在其中加入版本检查，权限认证等。</p><p>那  HBase是怎么设计这个RPC呢？首先它定义了一个writable接口，来代替java序列化，实现这个接口就等于告诉HBase，怎么把这个对象写  到RPC流中去。使用RPC的时候，需要先写一个服务器端和客户端共用的interface,这个interface必须继承  VersionedProtocol来处理版本问题&nbsp;。HBase利用Java的动态反射机制(Proxy.newProxyInstance)来生成代   理对象，这样当Client调用代理对象的时候，Client就会把参数打包，发送到服务器端，然后等待返回结果。服务器会根据interface查找到  具体的实现的对象，调用该对象的方法来执行远程调用。详细的做法可以参考HBase/Hadoop的源码。</p><p><strong>6.内嵌Web Server增强系统的透明度</strong><br /> 当一个后台进程启动之后，我们如何了解这个进程的内部状态呢？传统方法是通过进程管理器或者Debug log来看进程的情况，但是这些信息很有限。</p><p>HBase利用jetty在进程内部启动了一个web server，就可以即时的显示一些系统内部的信息，非常的方便。</p><p>利  用Jetty支持jsp非常的容易，下面是一个示例的代码。注意的是，需要把jasper-runtime-5.5.12.jar,jasper-  compiler-5.5.12.jar,jasper-compiler-jdt-5.5.12.jar,jsp-2.1.jar,jsp-api-  2.1.jar等jar包放在classpath里面，否则会出现页面解析错误。</p><p>server = new Server(port);</p><p>server.setSendServerVersion(false);<br /> server.setSendDateHeader(false);<br /> server.setStopAtShutdown(true);</p><p>WebAppContext wac = new WebAppContext();<br /> wac.setContextPath("/");<br /> wac.setWar("./webapps/job");<br /> server.setHandler(wac);<br /> server.setStopAtShutdown(true);</p></div><img src ="http://www.blogjava.net/sandy/aggbug/371379.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/sandy/" target="_blank">小明</a> 2012-03-07 10:42 <a href="http://www.blogjava.net/sandy/archive/2012/03/07/Learn_From_HBase.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>