之前分享的文章leveldb实现原理分析详细描述了LevelDB的实现原理,本文从Put接口来看下leveldb数据写流程的源码实现。
LevelDB的读写接口在类DB中定义(leveldb/db.h),接口声明如下:
// Set the database entry for "key" to "value". Returns OK on success, // and a non-OK status on error. // Note: consider setting options.sync = true. virtual Status Put(const WriteOptions& options, const Slice& key, const Slice& value) = 0; // Remove the database entry (if any) for "key". Returns OK on // success, and a non-OK status on error. It is not an error if "key" // did not exist in the database. // Note: consider setting options.sync = true. virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; // Apply the specified updates to the database. // Returns OK on success, non-OK on failure. // Note: consider setting options.sync = true. virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; // If the database contains an entry for "key" store the // corresponding value in *value and return OK. // // If there is no entry for "key" leave *value unchanged and return // a status for which Status::IsNotFound() returns true. // // May return some other Status on an error. virtual Status Get(const ReadOptions& options, const Slice& key, std::string* value) = 0;
而接口的实现则在DBImpl类中(leveldb/db_impl.h)。这篇文章跟随Put接口,去了解leveldb的内部实现。
DBImpl类中的Put方法实现如下:
它什么也没有做只是调用了父类DB的Put实现,DB::Put的实现如下:Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { return DB::Put(o, key, val); }
Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { WriteBatch batch; batch.Put(key, value); return Write(opt, &batch); }
父类的实现也很简单,就是将待写入的key-value放入WriteBatch对象中,然后调用了Write方法。在继续看Write方法实现之前,我们先看下这个方法用到的几个类:WriteOption,WriteBatch和Slice.它们的定义如下:
struct WriteOptions { // If true, the write will be flushed from the operating system // buffer cache (by calling WritableFile::Sync()) before the write // is considered complete. If this flag is true, writes will be // slower. // // If this flag is false, and the machine crashes, some recent // writes may be lost. Note that if it is just the process that // crashes (i.e., the machine does not reboot), no writes will be // lost even if sync==false. // // In other words, a DB write with sync==false has similar // crash semantics as the "write()" system call.