leveldb
来源:互联网 发布:建筑bim软件 编辑:程序博客网 时间:2024/06/06 19:33
int main(int argc, char** argv) { leveldb::DB* db; leveldb::Options options; // 如果打开已存在数据库的时候,需要抛出错误,将以下代码插在leveldb::DB::Open方法前面 options.create_if_missing = true; // 打开一个数据库实例 leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db); assert(status.ok()); // LevelDB提供了Put、Get和Delete三个方法对数据库进行添加、查询和删除 std::string key = "key"; std::string value = "value"; // 添加key=value status = db->Put(leveldb::WriteOptions(), key, value); assert(status.ok()); // 根据key查询value status = db->Get(leveldb::ReadOptions(), key, &value); assert(status.ok()); std::cout< // 修改操作(原生没有提供)由添加和删除合起来实现 std::string key2 = "key2"; // 添加key2=value status = db->Put(leveldb::WriteOptions(),key2,value); assert(status.ok()); // 删除key status = db->Delete(leveldb::WriteOptions(), key); // 查询key2 assert(status.ok()); status = db->Get(leveldb::ReadOptions(), key2, &value); assert(status.ok()); std::cout< // 查询key status = db->Get(leveldb::ReadOptions(), key, &value); if (!status.ok()) { std::cerr< } else { std::cout< } // 在对数据库进行了一系列的操作之后,需要对数据库进行关闭,该操作比较简单即删除该对象即可 delete db; return 0; } #g++ -o main main.cpp ../leveldb/libleveldb.a -lpthread -I../leveldb/include 实例编译完成后,如下来执行即可看到结果: #./main value key2==value key: NotFound:
一个LevelDB数据库需要有一个对应的文件系统目录名字,该数据库的所有内容都存储在这个目录下。
LevelDB的使用很简单,一般分三步走:
(1)打开一个数据库实例。
(2)对这个数据库实例进行插入,修改和查询操作。
(3)最后在使用完成之后,关闭该数据库。
对数据库的简单读、写操作LevelDB提供了Put,Delete和Get三个方法对数据库进行修改和查询
特点:
1、key和value都是任意长度的字节数组;
2、entry(即一条K-V记录)默认是按照key的字典顺序存储的,当然开发者也可以重载这个排序函数;
3、提供的基本操作接口:Put()、Delete()、Get()、Batch();
4、支持批量操作以原子操作进行;
5、可以创建数据全景的snapshot(快照),并允许在快照中查找数据;
6、可以通过前向(或后向)迭代器遍历数据(迭代器会隐含的创建一个snapshot);
7、自动使用Snappy压缩数据;
8、可移植性;
10.1.6 iterator.h
遍历器接口非常简单,支持前向和反向遍历。还支持seek到某一个key.支持注册cleanup函数.实现是DBIter.
class Iterator { public: Iterator(); virtual ~Iterator(); // An iterator is either positioned at a key/value pair, or // not valid. This method returns true iff the iterator is valid. virtual bool Valid() const = 0; // Position at the first key in the source. The iterator is Valid() // after this call iff the source is not empty. virtual void SeekToFirst() = 0; // Position at the last key in the source. The iterator is // Valid() after this call iff the source is not empty. virtual void SeekToLast() = 0; // Position at the first key in the source that at or past target // The iterator is Valid() after this call iff the source contains // an entry that comes at or past target. virtual void Seek(const Slice& target) = 0; // Moves to the next entry in the source. After this call, Valid() is // true iff the iterator was not positioned at the last entry in the source. // REQUIRES: Valid() virtual void Next() = 0; // Moves to the previous entry in the source. After this call, Valid() is // true iff the iterator was not positioned at the first entry in source. // REQUIRES: Valid() virtual void Prev() = 0; // Return the key for the current entry. The underlying storage for // the returned slice is valid only until the next modification of // the iterator. // REQUIRES: Valid() virtual Slice key() const = 0; // Return the value for the current entry. The underlying storage for // the returned slice is valid only until the next modification of // the iterator. // REQUIRES: !AtEnd() && !AtStart() virtual Slice value() const = 0; // If an error has occurred, return it. Else return an ok status. virtual Status status() const = 0; // Clients are allowed to register function/arg1/arg2 triples that // will be invoked when this iterator is destroyed. // // Note that unlike all of the preceding methods, this method is // not abstract and therefore clients should not override it. typedef void (*CleanupFunction)(void* arg1, void* arg2); void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); private: struct Cleanup { CleanupFunction function; void* arg1; void* arg2; Cleanup* next; }; Cleanup cleanup_; // No copying allowed Iterator(const Iterator&); void operator=(const Iterator&);};
这个里面部分实现在table/iterator.cc里面有.都非常简单.创建好cleanup对象然后组织称为链表,在析构函数时候调用.
Iterator::Iterator() { cleanup_.function = NULL; cleanup_.next = NULL;}Iterator::~Iterator() { if (cleanup_.function != NULL) { (*cleanup_.function)(cleanup_.arg1, cleanup_.arg2); for (Cleanup* c = cleanup_.next; c != NULL; ) { (*c->function)(c->arg1, c->arg2); Cleanup* next = c->next; delete c; c = next; } }}void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { assert(func != NULL); Cleanup* c; if (cleanup_.function == NULL) { c = &cleanup_; } else { c = new Cleanup; c->next = cleanup_.next; cleanup_.next = c; } c->function = func; c->arg1 = arg1; c->arg2 = arg2;}
IIteration下面的例子展示了如何打印数据库中的所有键值对。leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions()); for (it->SeekToFirst(); it->Valid(); it->Next()) { cout << it->key().ToString() << ": " << it->value().ToString() << endl; } assert(it->status().ok()); // Check for any errors found during the scan delete it; 下面的例子展示了如何访问key在[start,limit)范围内的情况:for (it->Seek(start); it->Valid() && it->key().ToString() < limit; it->Next()) { ...}下面展示了逆序访问(注意:逆序访问会比正序访问要慢)for (it->SeekToLast(); it->Valid(); it->Prev()) { ... }
原子更新操作在将key2插入之后key1删除之前调用的进程挂掉,在不同的key下存在相同的value。WriteBatch类可以通过一系列的更新操作来避免这个问题。#include "leveldb/write_batch.h"...std::string value;leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);if (s.ok()) { leveldb::WriteBatch batch; batch.Delete(key1); batch.Put(key2, value); s = db->Write(leveldb::WriteOptions(), &batch);}WriteBatch类顺序的执行一系列的操作。在例子中,要在插入之前调用删除操作。这样当key1和key2相同的时候,不需要结束错误的删除值的操作。WriteBatch类除了原子性的好处之外,可以大大加快大批量更新操作的速度。
1,下载levelDB源码Git clone https://github.com/google/leveldb.git2,编译LevelDBcd leveldb & make all编译完成之后在当前目录多了两个目录:out-shared和out-static在out-static目录下有我们需要的libleveldb.a3,在当前目录新建文件夹testtouch test; cd test4,在test目录新建测试代码test.cpp[cpp] view plain copyprint?在CODE上查看代码片派生到我的代码片 #include <assert.h> #include <string.h> #include <iostream> #include "leveldb/db.h" int main(){ leveldb::DB* db; leveldb::Options options; options.create_if_missing = true; leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb", &db); assert(status.ok()); std::string k1 = "name"; std::string v1 = "jim"; status = db->Put(leveldb::WriteOptions(), k1, v1); assert(status.ok()); status = db->Get(leveldb::ReadOptions(), k1, &v1); assert(status.ok()); std::cout<<"k1:"<<k1<<"; v1:"<<v1<<std::endl; std::string k2 = "age"; std::string v2 = "20"; status = db->Put(leveldb::WriteOptions(), k2, v2); assert(status.ok()); status = db->Get(leveldb::ReadOptions(), k2, &v2); assert(status.ok()); std::cout<<"k2:"<<k2<<"; v2:"<<v2<<std::endl; status = db->Delete(leveldb::WriteOptions(), k2); assert(status.ok()); std::cout<<"Delete k2.."<<std::endl; status = db->Get(leveldb::ReadOptions(),k2, &v2); if(!status.ok()) std::cerr<<"k2:"<<k2<<"; "<<status.ToString()<<std::endl; else std::cout<<"k2:"<<k2<<"; v2:"<<v2<<std::endl; delete db; return 0; } 5,编译前的准备把libleveldb.a拷贝到当前目录cp ../out-static/libleveldb.a ./把leveldb/include目录添加到PATH :cd ..; export PATH=$PATH:$(pwd)/include; cd test6,编译运行编译:g++ -o test test.cpp libleveldb.a -lpthread -I../include运行:[cpp] view plain copyprint?在CODE上查看代码片派生到我的代码片 ➜ test git:(master) ✗ ./test k1:name; v1:jim k2:age; v2:20 Delete k2.. k2:age; NotFound: 到目前为止,我们就基本可以使用leveldb了。9, 执行完.test之后,在/tmp/testdb下面产生了leveldb相关的文件:[cpp] view plain copyprint?在CODE上查看代码片派生到我的代码片 ➜ test git:(master) ✗ ls -alh /tmp/testdb total 56 drwxr-xr-x 10 root wheel 340B 10 3 12:51 . drwxrwxrwt 14 root wheel 476B 10 3 12:31 .. -rw-r--r-- 1 root wheel 148B 10 3 12:14 000005.ldb -rw-r--r-- 1 root wheel 148B 10 3 12:51 000008.ldb -rw-r--r-- 1 root wheel 80B 10 3 12:51 000009.log -rw-r--r-- 1 root wheel 16B 10 3 12:51 CURRENT -rw-r--r-- 1 root wheel 0B 10 3 11:57 LOCK -rw-r--r-- 1 root wheel 309B 10 3 12:51 LOG -rw-r--r-- 1 root wheel 309B 10 3 12:14 LOG.old -rw-r--r-- 1 root wheel 110B 10 3 12:51 MANIFEST-000007 8, 根据LevelDB官方网站的描述,LevelDB的特点和限制如下:特点:1、key和value都是任意长度的字节数组;2、entry(即一条K-V记录)默认是按照key的字典顺序存储的,当然开发者也可以重载这个排序函数;3、提供的基本操作接口:Put()、Delete()、Get()、Batch();4、支持批量操作以原子操作进行;5、可以创建数据全景的snapshot(快照),并允许在快照中查找数据;6、可以通过前向(或后向)迭代器遍历数据(迭代器会隐含的创建一个snapshot);7、自动使用Snappy压缩数据;8、可移植性;限制:1、非关系型数据模型(NoSQL),不支持sql语句,也不支持索引;2、一次只允许一个进程访问一个特定的数据库;3、没有内置的C/S架构,但开发者可以使用LevelDB库自己封装一个server;
0 0
- LevelDb
- LevelDb
- LevelDb
- leveldb
- leveldb
- leveldb
- leveldb
- LevelDb
- LevelDb
- Leveldb
- Leveldb
- levelDB
- LevelDb
- leveldb
- LevelDb
- LevelDb
- LevelDb
- leveldb
- STL算法 unique
- Java中int与Integer、Long与long有什么区别?
- JSP页面传值Action数据乱码问题
- 关于border-radius设置问题
- Java Collections的常见问题
- leveldb
- windows service宿主web api使用"依赖注入"和“控制反转”的技术实践
- 0305 HTML5基本格式
- Python学习之路(1)
- spss、R语言、Python数据分析系列(3):R语言从外部读取数据
- Javaweb简单笔记
- 整型
- 选择排序
- 学习一