LevelDB源码分析(一)安装编译和简单Demo

认识LevelDB & 源码下载编译

LevelDB是 Google 编写的key-value存储库,提供从Key到Value的有序映射。

LevelDB的代码量相比其他开源项目较少,除了测试之外大约有不到两万行代码。

LevelDB源码行数统计

Mac源码下载和编译运行

LevelDB下载地址:https://github.com/google/leveldb

  1. 下载与编译
git clone https://github.com/google/leveldb.git
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build . 

注意:上述命令编译的是Release版本,如果想要Debug,最后一条命令可以改为

cmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build . 

运行报错

CMake Error at CMakeLists.txt:299 (add_subdirectory):
  The source directory
 
    /home/xie/cpp/leveldb/third_party/googletest
 
  does not contain a CMakeLists.txt file.
 
 
CMake Error at CMakeLists.txt:304 (add_subdirectory):
  The source directory
 
    /home/xie/cpp/leveldb/third_party/benchmark
 
  does not contain a CMakeLists.txt file.
......

这是因为third_party下没有googletest和benchmark。

方法一:需要手动把这两个下载下来:

cd third_party
git clone https://github.com/google/benchmark.git
git clone https://github.com/google/googletest.git

方法二:自动下载

git submodule update --init

然后执行cmake命令就可以了。

  1. 执行测试

首先可以使用leveldb/benchmarks目录下的文件进行测试。
benchmark运行结果
snappy/crc32c/zstd/tcmalloc没有lib

snappy: levelDB中会使用snappy压缩算法来对数据进行压缩,能够在不影响读写性能的情况下减小数据存储空间。压缩速度为 250 MB/秒及以上,无需汇编代码。解压缩时会检测压缩流中是否存在错误。

# snappy的安装和编译
git clone https://github.com/google/snappy.git
cd snappy
git submodule update --init
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ../
make

然后在CMakeLists.txt中修改SNAPPY的配置。找到**check_library_exists(snappy snappy_compress “” HAVE_SNAPPY)**的位置,然后添加以下参数:

link_directories("/Users/julia/CLionProjects/others/snappy/build")
include_directories("/Users/julia/CLionProjects/others/snappy" "/Users/julia/CLionProjects/others/snappy/build")
#注意此行为原来的配置
check_library_exists(snappy snappy_compress "" HAVE_SNAPPY)
#结束
set(HAVE_SNAPPY ON)

然后重新编译LevelDB,运行db_bench得到如下结果:
安装snappy后的结果
可以看到snappy是启用的。

其次,我们可以自己写Demo进行测试。在CMakeLists所在目录下创建一个demo进行测试。

//
// Created by Julia on 2024/8/18.
//
#include <cstdio>
#include <iostream>

#include "leveldb/my_comparator.h"

#include "include/leveldb/db.h"
#include "include/leveldb/write_batch.h"

int main() {
    // Open a database.
    leveldb::DB* db;
    leveldb::Options opt;
    opt.create_if_missing = true;
    leveldb::Status status = leveldb::DB::Open(opt, "../db/testdb", &db);
    assert(status.ok());

    // Write data.
    status = db->Put(leveldb::WriteOptions(), "test_name", "sjl");
    assert(status.ok());

    // Read data.
    std::string value;
    status = db->Get(leveldb::ReadOptions(), "test_name", &value);
    assert(status.ok());
    std::cout << value << std::endl;

    // Delete data.
    status = db->Delete(leveldb::WriteOptions(), "test_name");
    assert(status.ok());

    // Atomic Updates
    status = db->Put(leveldb::WriteOptions(), "key1", "26");
    assert(status.ok());
    std::string value1;
    status = db->Get(leveldb::ReadOptions(), "key1", &value1);
    if(status.ok()) {
      leveldb::WriteBatch batch;
      batch.Delete("key1");
      batch.Put("key2", value1);
      status = db->Write(leveldb::WriteOptions(), &batch);
    }

    // Synchronous Writes
    // leveldb默认是异步写入,开启sync是会使写操作一直被数据传输到底层存储器后再返回。
    leveldb::WriteOptions write_potions;
    write_potions.sync = true;
    db->Put(write_potions, "key2", "girl");
    write_potions.sync = false;

    // Iteration 迭代打印键值对
    leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
    for (it->SeekToFirst(); it->Valid(); it->Next()) {
      std::cout << it->key().ToString() << ":" << it->value().ToString() << std::endl;
    }
    assert(it->status().ok());
    delete it;
    // 打印[start, limit)
    leveldb::Iterator* rangeIt = db->NewIterator(leveldb::ReadOptions());
    for (rangeIt->Seek("key2"); rangeIt->Valid() && rangeIt->key().ToString() < "key3"; rangeIt->Next()) {
      std::cout << rangeIt->key().ToString() << ":" << rangeIt->value().ToString() << std::endl;
    }
    // 反向迭代
    for(rangeIt->SeekToLast(); rangeIt->Valid(); rangeIt->Prev()) {
      std::cout << rangeIt->key().ToString() << ":" << rangeIt->value().ToString() << std::endl;
    }
    delete rangeIt;

    // Snapshot
    leveldb::ReadOptions options;
    options.snapshot = db->GetSnapshot();
    db->Put(write_potions, "key2", "new_girl");
    leveldb::Iterator* itSnap = db->NewIterator(options);
    itSnap->Seek("key2");
    std::cout << itSnap->key().ToString() << ":" << itSnap->value().ToString() << std::endl;
    delete itSnap;
    db->ReleaseSnapshot(options.snapshot);

    // Slice: it->key(), it->value() 返回的值就是Slice类型,Slice类型包含一个length和一个指向外部字节数组的指针。
    leveldb::Slice s1 = "hello";
    std::string str("world");
    leveldb::Slice s2 = str;
    std::string str2 = s1.ToString();
    assert(str2 == std::string("hello"));

    // Close
    delete db;

    // Comparators
    MyComparator cmp;
    leveldb::DB* db2;
    leveldb::Options options2;
    options2.create_if_missing = true;
    options2.comparator = &cmp;
    leveldb::Status status1 = leveldb::DB::Open(options2, "../db/myComparatorDB2", &db2);
    assert(status1.ok());
    leveldb::WriteBatch batch2;
    batch2.Put("1", "1");
    batch2.Put("2", "2");
    batch2.Put("3", "3");
    status1 = db2->Write(leveldb::WriteOptions(), &batch2);
    assert(status1.ok());
    leveldb::Iterator* it2 = db2->NewIterator(leveldb::ReadOptions());
    for (it2->SeekToFirst(); it2->Valid(); it2->Next()) {
      std::cout << it2->key().ToString() << ":" << it2->value().ToString() << std::endl;
    }
    delete it2;
    delete db2;



    // Compression :
    // options.compression = leveldb::kNoCompression;

    // Cache :
    // options.cache = leveldb::NewLRUCache(100 * 1048576);  // 100MB cache
    // delete options.cache;
    // 缓存里存放的时未压缩的数据
    // 禁用缓存
    // options.fill_cache = false;

    // BloomFilter : 通过对key增加数据位来减少磁盘读取的操作次数
    // options.filter_policy = NewBloomFilterPolicy(10);
    // delete options.filter_policy;

}
//
// Created by Julia on 2024/8/20.
//

#include "comparator.h"
#include "slice.h"
#ifndef LEVELDB_MY_COMPARATOR_H
#define LEVELDB_MY_COMPARATOR_H

#endif  // LEVELDB_MY_COMPARATOR_H
class MyComparator : public leveldb::Comparator {
 public:
  int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const override {
    return leveldb::BytewiseComparator()->Compare(b, a);
  }
  // Ignore the following methods for now:
  const char* Name() const override { return "MyComparator"; }
  void FindShortestSeparator(std::string*, const leveldb::Slice&) const override{ }
  void FindShortSuccessor(std::string*) const override{ }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值