leveldb源码分析 之 入门使用
2015-12-21 10:17
477 查看
转自 http://qiuqiang1985.iteye.com/blog/1255365
LevelDB是google开源的一个key-value存储引擎库,类似于开源的Lucene索引库一样。其他的软件开发者可以利用该库做二次开发,来满足定制需求。LevelDB采用日志式的写方式来提高写性能,但是牺牲了部分读性能。为了弥补牺牲了的读性能,一些人提议使用SSD作为存储介质。
对于本地化的Key-value存储引擎来说,简单的使用一般都分成三个基本的步骤:(1)打开一个数据库实例;(2)对这个数据库实例进行插入,修改和查询操作;(3)最后在使用完成之后,关闭该数据库。下面将详细讨论该三个步骤:
一、打开一个数据库实例
一个leveldb数据库有一个对应一个文件系统目录的名字。该数据库的所有内容都存储在这个目录下。下面的代码描述了怎样打开一个数据库或者建立一个新的数据库。
Cpp代码
#include <assert.h>
#include "leveldb/db.h"
leveldb::DB* db;
leveldb::Options options;
options.create_if_missing = true;
leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb", &db);
assert(status.ok());
如果打开已存在数据库的时候,需要抛出错误。将以下代码插在leveldb::DB::Open方法前面:
options.error_if_exists = true;
二、对数据库的简单读、写操作
LevelDB提供了Put,Delete和Get三个方法对数据库进行修改和查询。例如,下面的代码片段描述了怎样将key1对应的value值,移到key2对应的值。
C代码
std::string value;
leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
if(s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);
if(s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);
三、关闭数据库
在对数据库进行了一系列的操作之后,需要对数据库进行关闭。该操作比较简单:
C代码
... open the db as described above...
... do something with db ...
delete db;
上面对levelDB的简单使用做了基本的介绍,接下来就是如何自己写一个完成并且能运行的例子。
1、下载源码 git clone https://code.google.com/p/leveldb/
2、编译源码 cd leveldb && make all
3、编写test.cpp
C代码
#include <assert.h>
#include <string.h>
#include <leveldb/db.h>
#include <iostream>
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());
//write key1,value1
std::string key="key";
std::string value = "value";
status = db->Put(leveldb::WriteOptions(), key,value);
assert(status.ok());
status = db->Get(leveldb::ReadOptions(), key, &value);
assert(status.ok());
std::cout<<value<<std::endl;
std::string key2 = "key2";
//move the value under key to key2
status = db->Put(leveldb::WriteOptions(),key2,value);
assert(status.ok());
status = db->Delete(leveldb::WriteOptions(), key);
assert(status.ok());
status = db->Get(leveldb::ReadOptions(),key2, &value);
assert(status.ok());
std::cout<<key2<<"==="<<value<<std::endl;
status = db->Get(leveldb::ReadOptions(),key, &value);
if(!status.ok()) std::cerr<<key<<" "<<status.ToString()<<std::endl;
else std::cout<<key<<"==="<<value<<std::endl;
delete db;
return 0;
}
4、编译链接 g++ -o test test.cpp ../leveldb/libleveldb.a -lpthread -I../leveldb/include
注意libleveldb.a 和leveldb include的路径。
5、运行结果./test:
C代码
value
key2===value
key NotFound:
levelDB源码分析-Status
转自 http://qiuqiang1985.iteye.com/blog/1255365
leveldb::Status表示levelDB的一个返回状态,通常的错误处理(如:errno)是返回一个错误号,然后根据错误号可以获得出错的描述信息。
leveldb将错误号和错误信息封装成Status类,来统一进行处理。
声明如下:
[cpp] view
plaincopy
<span style="font-size:18px;"> class Status {
public:
// Create a success status.
Status() : state_(NULL) { } // 构造函数,默认状态为success
~Status() { delete[] state_; } // 析构函数,释放状态字符串
// Copy the specified status.
Status(const Status& s);
void operator=(const Status& s);
// Return a success status.
static Status OK() { return Status(); } // 返回一个success的状态
// Return error status of an appropriate type.
static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { //
return Status(kNotFound, msg, msg2);
}
static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kCorruption, msg, msg2);
}
static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kNotSupported, msg, msg2);
}
static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kInvalidArgument, msg, msg2);
}
static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kIOError, msg, msg2);
}
// Returns true iff the status indicates success.
bool ok() const { return (state_ == NULL); }
// Returns true iff the status indicates a NotFound error.
bool IsNotFound() const { return code() == kNotFound; }
// Return a string representation of this status suitable for printing.
// Returns the string "OK" for success.
std::string ToString() const;
private:
// 为了节省空间Status并没有用std::string来存储错误信息,
// 而是将返回码(Code), 错误信息msg及长度打包存储于一个字符串数组中。
// OK status has a NULL state_. Otherwise, state_ is a new[] array of the following form:
// state_[0..3] == length of message
// state_[4] == code
// state_[5..] == message
const char* state_;
enum Code {
kOk = 0,
kNotFound = 1,
kCorruption = 2,
kNotSupported = 3,
kInvalidArgument = 4,
kIOError = 5
};
Code code() const { // 返回状态码
return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
}
Status(Code code, const Slice& msg, const Slice& msg2); // 内部构造函数
static const char* CopyState(const char* s); //
};
</span>
实现如下:
[cpp] view
plaincopy
<span style="font-size:18px;"> inline Status::Status(const Status& s) { // 拷贝构造函数
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}
inline void Status::operator=(const Status& s) { // 赋值运算符重载
// The following condition catches both aliasing (when this == &s),
// and the common case where both s and *this are ok.
if (state_ != s.state_) {
delete[] state_;
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}
}
const char* Status::CopyState(const char* state) { // 复制状态字符串
uint32_t size;
memcpy(&size, state, sizeof(size));
uint32_t len = size + sizeof(size) + 1 ;
char* result = new char[len];
memcpy(result, state, len);
return result;
}
Status::Status(Code code, const Slice& msg, const Slice& msg2) { // 内部构造函数
assert(code != kOk);
const uint32_t len1 = msg.size();
const uint32_t len2 = msg2.size();
const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
char* result = new char[size + 6]; // 没有结束符? --- 由于保留了size字段,采用memcpy指定size操作,可以没有结束符
memcpy(result, &size, sizeof(size));
result[4] = static_cast<char>(code); // 第5个字节存放code
//memcpy(result + 5, msg.data(), len1);
memcpy(result + sizeof(size) + 1, msg.data(), len1);
if (len2) {
result[5 + len1] = ':';
result[6 + len1] = ' ';
memcpy(result + 7 + len1, msg2.data(), len2);
}
state_ = result;
}
std::string Status::ToString() const { // 返回状态字符串
if (state_ == NULL) {
return "OK";
} else {
char tmp[30];
const char* type;
switch (code()) {
case kOk:
type = "OK";
break;
case kNotFound:
type = "NotFound: ";
break;
case kCorruption:
type = "Corruption: ";
break;
case kNotSupported:
type = "Not implemented: ";
break;
case kInvalidArgument:
type = "Invalid argument: ";
break;
case kIOError:
type = "IO error: ";
break;
default:
snprintf(tmp, sizeof(tmp), "Unknown code(%d): ", static_cast<int>(code()));
type = tmp;
break;
}
std::string result(type);
uint32_t length;
memcpy(&length, state_, sizeof(length));
result.append(state_ + 5, length); // 状态字符串
return result;
}
}</span>
使用方法:
[cpp] view
plaincopy
<span style="font-size:18px;"> Status status_ = Status::Corruption("bad entry in block");
Status::Corruption("bad block contents") ;
Status::InvalidArgument((string)dbname_, "does not exist (create_if_missing is false)");
Status::Corruption("log record too small");
Status s = Status::IOError("Deleting DB during memtable compaction");
Status::OK() ;
status.ToString() ;
</span>
LevelDB是google开源的一个key-value存储引擎库,类似于开源的Lucene索引库一样。其他的软件开发者可以利用该库做二次开发,来满足定制需求。LevelDB采用日志式的写方式来提高写性能,但是牺牲了部分读性能。为了弥补牺牲了的读性能,一些人提议使用SSD作为存储介质。
对于本地化的Key-value存储引擎来说,简单的使用一般都分成三个基本的步骤:(1)打开一个数据库实例;(2)对这个数据库实例进行插入,修改和查询操作;(3)最后在使用完成之后,关闭该数据库。下面将详细讨论该三个步骤:
一、打开一个数据库实例
一个leveldb数据库有一个对应一个文件系统目录的名字。该数据库的所有内容都存储在这个目录下。下面的代码描述了怎样打开一个数据库或者建立一个新的数据库。
Cpp代码
#include <assert.h>
#include "leveldb/db.h"
leveldb::DB* db;
leveldb::Options options;
options.create_if_missing = true;
leveldb::Status status = leveldb::DB::Open(options,"/tmp/testdb", &db);
assert(status.ok());
如果打开已存在数据库的时候,需要抛出错误。将以下代码插在leveldb::DB::Open方法前面:
options.error_if_exists = true;
二、对数据库的简单读、写操作
LevelDB提供了Put,Delete和Get三个方法对数据库进行修改和查询。例如,下面的代码片段描述了怎样将key1对应的value值,移到key2对应的值。
C代码
std::string value;
leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
if(s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);
if(s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);
三、关闭数据库
在对数据库进行了一系列的操作之后,需要对数据库进行关闭。该操作比较简单:
C代码
... open the db as described above...
... do something with db ...
delete db;
上面对levelDB的简单使用做了基本的介绍,接下来就是如何自己写一个完成并且能运行的例子。
1、下载源码 git clone https://code.google.com/p/leveldb/
2、编译源码 cd leveldb && make all
3、编写test.cpp
C代码
#include <assert.h>
#include <string.h>
#include <leveldb/db.h>
#include <iostream>
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());
//write key1,value1
std::string key="key";
std::string value = "value";
status = db->Put(leveldb::WriteOptions(), key,value);
assert(status.ok());
status = db->Get(leveldb::ReadOptions(), key, &value);
assert(status.ok());
std::cout<<value<<std::endl;
std::string key2 = "key2";
//move the value under key to key2
status = db->Put(leveldb::WriteOptions(),key2,value);
assert(status.ok());
status = db->Delete(leveldb::WriteOptions(), key);
assert(status.ok());
status = db->Get(leveldb::ReadOptions(),key2, &value);
assert(status.ok());
std::cout<<key2<<"==="<<value<<std::endl;
status = db->Get(leveldb::ReadOptions(),key, &value);
if(!status.ok()) std::cerr<<key<<" "<<status.ToString()<<std::endl;
else std::cout<<key<<"==="<<value<<std::endl;
delete db;
return 0;
}
4、编译链接 g++ -o test test.cpp ../leveldb/libleveldb.a -lpthread -I../leveldb/include
注意libleveldb.a 和leveldb include的路径。
5、运行结果./test:
C代码
value
key2===value
key NotFound:
levelDB源码分析-Status
转自 http://qiuqiang1985.iteye.com/blog/1255365
leveldb::Status表示levelDB的一个返回状态,通常的错误处理(如:errno)是返回一个错误号,然后根据错误号可以获得出错的描述信息。
leveldb将错误号和错误信息封装成Status类,来统一进行处理。
声明如下:
[cpp] view
plaincopy
<span style="font-size:18px;"> class Status {
public:
// Create a success status.
Status() : state_(NULL) { } // 构造函数,默认状态为success
~Status() { delete[] state_; } // 析构函数,释放状态字符串
// Copy the specified status.
Status(const Status& s);
void operator=(const Status& s);
// Return a success status.
static Status OK() { return Status(); } // 返回一个success的状态
// Return error status of an appropriate type.
static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { //
return Status(kNotFound, msg, msg2);
}
static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kCorruption, msg, msg2);
}
static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kNotSupported, msg, msg2);
}
static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kInvalidArgument, msg, msg2);
}
static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kIOError, msg, msg2);
}
// Returns true iff the status indicates success.
bool ok() const { return (state_ == NULL); }
// Returns true iff the status indicates a NotFound error.
bool IsNotFound() const { return code() == kNotFound; }
// Return a string representation of this status suitable for printing.
// Returns the string "OK" for success.
std::string ToString() const;
private:
// 为了节省空间Status并没有用std::string来存储错误信息,
// 而是将返回码(Code), 错误信息msg及长度打包存储于一个字符串数组中。
// OK status has a NULL state_. Otherwise, state_ is a new[] array of the following form:
// state_[0..3] == length of message
// state_[4] == code
// state_[5..] == message
const char* state_;
enum Code {
kOk = 0,
kNotFound = 1,
kCorruption = 2,
kNotSupported = 3,
kInvalidArgument = 4,
kIOError = 5
};
Code code() const { // 返回状态码
return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
}
Status(Code code, const Slice& msg, const Slice& msg2); // 内部构造函数
static const char* CopyState(const char* s); //
};
</span>
实现如下:
[cpp] view
plaincopy
<span style="font-size:18px;"> inline Status::Status(const Status& s) { // 拷贝构造函数
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}
inline void Status::operator=(const Status& s) { // 赋值运算符重载
// The following condition catches both aliasing (when this == &s),
// and the common case where both s and *this are ok.
if (state_ != s.state_) {
delete[] state_;
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}
}
const char* Status::CopyState(const char* state) { // 复制状态字符串
uint32_t size;
memcpy(&size, state, sizeof(size));
uint32_t len = size + sizeof(size) + 1 ;
char* result = new char[len];
memcpy(result, state, len);
return result;
}
Status::Status(Code code, const Slice& msg, const Slice& msg2) { // 内部构造函数
assert(code != kOk);
const uint32_t len1 = msg.size();
const uint32_t len2 = msg2.size();
const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
char* result = new char[size + 6]; // 没有结束符? --- 由于保留了size字段,采用memcpy指定size操作,可以没有结束符
memcpy(result, &size, sizeof(size));
result[4] = static_cast<char>(code); // 第5个字节存放code
//memcpy(result + 5, msg.data(), len1);
memcpy(result + sizeof(size) + 1, msg.data(), len1);
if (len2) {
result[5 + len1] = ':';
result[6 + len1] = ' ';
memcpy(result + 7 + len1, msg2.data(), len2);
}
state_ = result;
}
std::string Status::ToString() const { // 返回状态字符串
if (state_ == NULL) {
return "OK";
} else {
char tmp[30];
const char* type;
switch (code()) {
case kOk:
type = "OK";
break;
case kNotFound:
type = "NotFound: ";
break;
case kCorruption:
type = "Corruption: ";
break;
case kNotSupported:
type = "Not implemented: ";
break;
case kInvalidArgument:
type = "Invalid argument: ";
break;
case kIOError:
type = "IO error: ";
break;
default:
snprintf(tmp, sizeof(tmp), "Unknown code(%d): ", static_cast<int>(code()));
type = tmp;
break;
}
std::string result(type);
uint32_t length;
memcpy(&length, state_, sizeof(length));
result.append(state_ + 5, length); // 状态字符串
return result;
}
}</span>
使用方法:
[cpp] view
plaincopy
<span style="font-size:18px;"> Status status_ = Status::Corruption("bad entry in block");
Status::Corruption("bad block contents") ;
Status::InvalidArgument((string)dbname_, "does not exist (create_if_missing is false)");
Status::Corruption("log record too small");
Status s = Status::IOError("Deleting DB during memtable compaction");
Status::OK() ;
status.ToString() ;
</span>
相关文章推荐
- redhat ftp服务器设置
- C++编程实践: 抽象基类
- linux下svn的用法
- 利用递归级联删除的代码
- OpenGL 无法打开文件“freeglut_static.lib
- 玩转RobotFramework下的Web自动化测试(二)——关于上篇文章的一些思考
- python3 抓取必应bing首页图片作为桌面背景
- pig脚本记录,对于pig脚本跑批处理
- js为元素增加流动边框效果
- 嵌入式c语言面试题
- 获取Objc 类方法及属性的研究实现
- 简单涉猎各种博弈
- thinkphp-url地址影藏入口文件index.php
- vs2015产品密钥
- 获取Objc 类方法及属性的研究实现
- php的命名空间
- public void onClick(View arg0)
- LeetCode Remove Nth Node From End of List
- SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
- linux安装部署jdk,卸载系统自带jdk版本