Packages
rocksdb
0.23.0
3.1.1
3.1.0
3.0.0
2.6.2
2.6.1
retired
2.6.0
retired
2.5.0
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
1.9.0
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.1
1.1.0
1.0.0
0.26.2
0.26.1
0.26.0
0.25.0
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.0
0.21.0
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
RocksDB for Erlang
Current section
Files
Jump to
Current section
Files
deps/rocksdb/tools/rdb/db_wrapper.cc
#include <iostream>
#include <memory>
#include <vector>
#include <v8.h>
#include <node.h>
#include "db/_wrapper.h"
#include "rocksdb/db.h"
#include "rocksdb/options.h"
#include "rocksdb/slice.h"
namespace {
void printWithBackSlashes(std::string str) {
for (std::string::size_type i = 0; i < str.size(); i++) {
if (str[i] == '\\' || str[i] == '"') {
std::cout << "\\";
}
std::cout << str[i];
}
}
bool has_key_for_array(Local<Object> obj, std::string key) {
return obj->Has(String::NewSymbol(key.c_str())) &&
obj->Get(String::NewSymbol(key.c_str()))->IsArray();
}
}
using namespace v8;
Persistent<Function> DBWrapper::constructor;
DBWrapper::DBWrapper() {
options_.IncreaseParallelism();
options_.OptimizeLevelStyleCompaction();
options_.disable_auto_compactions = true;
options_.create_if_missing = true;
}
DBWrapper::~DBWrapper() {
delete db_;
}
bool DBWrapper::HasFamilyNamed(std::string& name, DBWrapper* db) {
return db->columnFamilies_.find(name) != db->columnFamilies_.end();
}
void DBWrapper::Init(Handle<Object> exports) {
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("DBWrapper"));
tpl->InstanceTemplate()->SetInternalFieldCount(8);
tpl->PrototypeTemplate()->Set(String::NewSymbol("open"),
FunctionTemplate::New(Open)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("get"),
FunctionTemplate::New(Get)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("put"),
FunctionTemplate::New(Put)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("delete"),
FunctionTemplate::New(Delete)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("dump"),
FunctionTemplate::New(Dump)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("createColumnFamily"),
FunctionTemplate::New(CreateColumnFamily)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("writeBatch"),
FunctionTemplate::New(WriteBatch)->GetFunction());
tpl->PrototypeTemplate()->Set(String::NewSymbol("compactRange"),
FunctionTemplate::New(CompactRange)->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
exports->Set(String::NewSymbol("DBWrapper"), constructor);
}
Handle<Value> DBWrapper::Open(const Arguments& args) {
HandleScope scope;
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
if (!(args[0]->IsString() &&
(args[1]->IsUndefined() || args[1]->IsArray()))) {
return scope.Close(Boolean::New(false));
}
std::string db_file = *v8::String::Utf8Value(args[0]->ToString());
std::vector<std::string> cfs = { rocksdb::kDefaultColumnFamilyName };
if (!args[1]->IsUndefined()) {
Handle<Array> array = Handle<Array>::Cast(args[1]);
for (uint i = 0; i < array->Length(); i++) {
if (!array->Get(i)->IsString()) {
return scope.Close(Boolean::New(false));
}
cfs.push_back(*v8::String::Utf8Value(array->Get(i)->ToString()));
}
}
if (cfs.size() == 1) {
db_wrapper->status_ = rocksdb::DB::Open(
db_wrapper->options_, db_file, &db_wrapper->db_);
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
std::vector<rocksdb::ColumnFamilyDescriptor> families;
for (std::vector<int>::size_type i = 0; i < cfs.size(); i++) {
families.push_back(rocksdb::ColumnFamilyDescriptor(
cfs[i], rocksdb::ColumnFamilyOptions()));
}
std::vector<rocksdb::ColumnFamilyHandle*> handles;
db_wrapper->status_ = rocksdb::DB::Open(
db_wrapper->options_, db_file, families, &handles, &db_wrapper->db_);
if (!db_wrapper->status_.ok()) {
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
for (std::vector<int>::size_type i = 0; i < handles.size(); i++) {
db_wrapper->columnFamilies_[cfs[i]] = handles[i];
}
return scope.Close(Boolean::New(true));
}
Handle<Value> DBWrapper::New(const Arguments& args) {
HandleScope scope;
Handle<Value> to_return;
if (args.IsConstructCall()) {
DBWrapper* db_wrapper = new DBWrapper();
db_wrapper->Wrap(args.This());
return args.This();
}
const int argc = 0;
Local<Value> argv[0] = {};
return scope.Close(constructor->NewInstance(argc, argv));
}
Handle<Value> DBWrapper::Get(const Arguments& args) {
HandleScope scope;
if (!(args[0]->IsString() &&
(args[1]->IsUndefined() || args[1]->IsString()))) {
return scope.Close(Null());
}
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
std::string key = *v8::String::Utf8Value(args[0]->ToString());
std::string cf = *v8::String::Utf8Value(args[1]->ToString());
std::string value;
if (args[1]->IsUndefined()) {
db_wrapper->status_ = db_wrapper->db_->Get(
rocksdb::ReadOptions(), key, &value);
} else if (db_wrapper->HasFamilyNamed(cf, db_wrapper)) {
db_wrapper->status_ = db_wrapper->db_->Get(
rocksdb::ReadOptions(), db_wrapper->columnFamilies_[cf], key, &value);
} else {
return scope.Close(Null());
}
Handle<Value> v = db_wrapper->status_.ok() ?
String::NewSymbol(value.c_str()) : Null();
return scope.Close(v);
}
Handle<Value> DBWrapper::Put(const Arguments& args) {
HandleScope scope;
if (!(args[0]->IsString() && args[1]->IsString() &&
(args[2]->IsUndefined() || args[2]->IsString()))) {
return scope.Close(Boolean::New(false));
}
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
std::string key = *v8::String::Utf8Value(args[0]->ToString());
std::string value = *v8::String::Utf8Value(args[1]->ToString());
std::string cf = *v8::String::Utf8Value(args[2]->ToString());
if (args[2]->IsUndefined()) {
db_wrapper->status_ = db_wrapper->db_->Put(
rocksdb::WriteOptions(), key, value
);
} else if (db_wrapper->HasFamilyNamed(cf, db_wrapper)) {
db_wrapper->status_ = db_wrapper->db_->Put(
rocksdb::WriteOptions(),
db_wrapper->columnFamilies_[cf],
key,
value
);
} else {
return scope.Close(Boolean::New(false));
}
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
Handle<Value> DBWrapper::Delete(const Arguments& args) {
HandleScope scope;
if (!args[0]->IsString()) {
return scope.Close(Boolean::New(false));
}
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
std::string arg0 = *v8::String::Utf8Value(args[0]->ToString());
std::string arg1 = *v8::String::Utf8Value(args[1]->ToString());
if (args[1]->IsUndefined()) {
db_wrapper->status_ = db_wrapper->db_->Delete(
rocksdb::WriteOptions(), arg0);
} else {
if (!db_wrapper->HasFamilyNamed(arg1, db_wrapper)) {
return scope.Close(Boolean::New(false));
}
db_wrapper->status_ = db_wrapper->db_->Delete(
rocksdb::WriteOptions(), db_wrapper->columnFamilies_[arg1], arg0);
}
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
Handle<Value> DBWrapper::Dump(const Arguments& args) {
HandleScope scope;
std::unique_ptr<rocksdb::Iterator> iterator;
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
std::string arg0 = *v8::String::Utf8Value(args[0]->ToString());
if (args[0]->IsUndefined()) {
iterator.reset(db_wrapper->db_->NewIterator(rocksdb::ReadOptions()));
} else {
if (!db_wrapper->HasFamilyNamed(arg0, db_wrapper)) {
return scope.Close(Boolean::New(false));
}
iterator.reset(db_wrapper->db_->NewIterator(
rocksdb::ReadOptions(), db_wrapper->columnFamilies_[arg0]));
}
iterator->SeekToFirst();
while (iterator->Valid()) {
std::cout << "\"";
printWithBackSlashes(iterator->key().ToString());
std::cout << "\" => \"";
printWithBackSlashes(iterator->value().ToString());
std::cout << "\"\n";
iterator->Next();
}
return scope.Close(Boolean::New(true));
}
Handle<Value> DBWrapper::CreateColumnFamily(const Arguments& args) {
HandleScope scope;
if (!args[0]->IsString()) {
return scope.Close(Boolean::New(false));
}
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
std::string cf_name = *v8::String::Utf8Value(args[0]->ToString());
if (db_wrapper->HasFamilyNamed(cf_name, db_wrapper)) {
return scope.Close(Boolean::New(false));
}
rocksdb::ColumnFamilyHandle* cf;
db_wrapper->status_ = db_wrapper->db_->CreateColumnFamily(
rocksdb::ColumnFamilyOptions(), cf_name, &cf);
if (!db_wrapper->status_.ok()) {
return scope.Close(Boolean::New(false));
}
db_wrapper->columnFamilies_[cf_name] = cf;
return scope.Close(Boolean::New(true));
}
bool DBWrapper::AddToBatch(rocksdb::WriteBatch& batch, bool del,
Handle<Array> array) {
Handle<Array> put_pair;
for (uint i = 0; i < array->Length(); i++) {
if (del) {
if (!array->Get(i)->IsString()) {
return false;
}
batch.Delete(*v8::String::Utf8Value(array->Get(i)->ToString()));
continue;
}
if (!array->Get(i)->IsArray()) {
return false;
}
put_pair = Handle<Array>::Cast(array->Get(i));
if (!put_pair->Get(0)->IsString() || !put_pair->Get(1)->IsString()) {
return false;
}
batch.Put(
*v8::String::Utf8Value(put_pair->Get(0)->ToString()),
*v8::String::Utf8Value(put_pair->Get(1)->ToString()));
}
return true;
}
bool DBWrapper::AddToBatch(rocksdb::WriteBatch& batch, bool del,
Handle<Array> array, DBWrapper* db_wrapper,
std::string cf) {
Handle<Array> put_pair;
for (uint i = 0; i < array->Length(); i++) {
if (del) {
if (!array->Get(i)->IsString()) {
return false;
}
batch.Delete(
db_wrapper->columnFamilies_[cf],
*v8::String::Utf8Value(array->Get(i)->ToString()));
continue;
}
if (!array->Get(i)->IsArray()) {
return false;
}
put_pair = Handle<Array>::Cast(array->Get(i));
if (!put_pair->Get(0)->IsString() || !put_pair->Get(1)->IsString()) {
return false;
}
batch.Put(
db_wrapper->columnFamilies_[cf],
*v8::String::Utf8Value(put_pair->Get(0)->ToString()),
*v8::String::Utf8Value(put_pair->Get(1)->ToString()));
}
return true;
}
Handle<Value> DBWrapper::WriteBatch(const Arguments& args) {
HandleScope scope;
if (!args[0]->IsArray()) {
return scope.Close(Boolean::New(false));
}
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
Handle<Array> sub_batches = Handle<Array>::Cast(args[0]);
Local<Object> sub_batch;
rocksdb::WriteBatch batch;
bool well_formed;
for (uint i = 0; i < sub_batches->Length(); i++) {
if (!sub_batches->Get(i)->IsObject()) {
return scope.Close(Boolean::New(false));
}
sub_batch = sub_batches->Get(i)->ToObject();
if (sub_batch->Has(String::NewSymbol("column_family"))) {
if (!has_key_for_array(sub_batch, "put") &&
!has_key_for_array(sub_batch, "delete")) {
return scope.Close(Boolean::New(false));
}
well_formed = db_wrapper->AddToBatch(
batch, false,
Handle<Array>::Cast(sub_batch->Get(String::NewSymbol("put"))),
db_wrapper, *v8::String::Utf8Value(sub_batch->Get(
String::NewSymbol("column_family"))));
well_formed = db_wrapper->AddToBatch(
batch, true,
Handle<Array>::Cast(sub_batch->Get(String::NewSymbol("delete"))),
db_wrapper, *v8::String::Utf8Value(sub_batch->Get(
String::NewSymbol("column_family"))));
} else {
well_formed = db_wrapper->AddToBatch(
batch, false,
Handle<Array>::Cast(sub_batch->Get(String::NewSymbol("put"))));
well_formed = db_wrapper->AddToBatch(
batch, true,
Handle<Array>::Cast(sub_batch->Get(String::NewSymbol("delete"))));
if (!well_formed) {
return scope.Close(Boolean::New(false));
}
}
}
db_wrapper->status_ = db_wrapper->db_->Write(rocksdb::WriteOptions(), &batch);
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
Handle<Value> DBWrapper::CompactRangeDefault(const Arguments& args) {
HandleScope scope;
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
rocksdb::Slice begin = *v8::String::Utf8Value(args[0]->ToString());
rocksdb::Slice end = *v8::String::Utf8Value(args[1]->ToString());
db_wrapper->status_ = db_wrapper->db_->CompactRange(&end, &begin);
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
Handle<Value> DBWrapper::CompactColumnFamily(const Arguments& args) {
HandleScope scope;
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
rocksdb::Slice begin = *v8::String::Utf8Value(args[0]->ToString());
rocksdb::Slice end = *v8::String::Utf8Value(args[1]->ToString());
std::string cf = *v8::String::Utf8Value(args[2]->ToString());
db_wrapper->status_ = db_wrapper->db_->CompactRange(
db_wrapper->columnFamilies_[cf], &begin, &end);
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
Handle<Value> DBWrapper::CompactOptions(const Arguments& args) {
HandleScope scope;
if (!args[2]->IsObject()) {
return scope.Close(Boolean::New(false));
}
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
rocksdb::Slice begin = *v8::String::Utf8Value(args[0]->ToString());
rocksdb::Slice end = *v8::String::Utf8Value(args[1]->ToString());
Local<Object> options = args[2]->ToObject();
int target_level = -1, target_path_id = 0;
if (options->Has(String::NewSymbol("target_level")) &&
options->Get(String::NewSymbol("target_level"))->IsInt32()) {
target_level = (int)(options->Get(
String::NewSymbol("target_level"))->ToInt32()->Value());
if (options->Has(String::NewSymbol("target_path_id")) ||
options->Get(String::NewSymbol("target_path_id"))->IsInt32()) {
target_path_id = (int)(options->Get(
String::NewSymbol("target_path_id"))->ToInt32()->Value());
}
}
db_wrapper->status_ = db_wrapper->db_->CompactRange(
&begin, &end, true, target_level, target_path_id
);
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
Handle<Value> DBWrapper::CompactAll(const Arguments& args) {
HandleScope scope;
if (!args[2]->IsObject() || !args[3]->IsString()) {
return scope.Close(Boolean::New(false));
}
DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
rocksdb::Slice begin = *v8::String::Utf8Value(args[0]->ToString());
rocksdb::Slice end = *v8::String::Utf8Value(args[1]->ToString());
Local<Object> options = args[2]->ToObject();
std::string cf = *v8::String::Utf8Value(args[3]->ToString());
int target_level = -1, target_path_id = 0;
if (options->Has(String::NewSymbol("target_level")) &&
options->Get(String::NewSymbol("target_level"))->IsInt32()) {
target_level = (int)(options->Get(
String::NewSymbol("target_level"))->ToInt32()->Value());
if (options->Has(String::NewSymbol("target_path_id")) ||
options->Get(String::NewSymbol("target_path_id"))->IsInt32()) {
target_path_id = (int)(options->Get(
String::NewSymbol("target_path_id"))->ToInt32()->Value());
}
}
db_wrapper->status_ = db_wrapper->db_->CompactRange(
db_wrapper->columnFamilies_[cf], &begin, &end, true, target_level,
target_path_id);
return scope.Close(Boolean::New(db_wrapper->status_.ok()));
}
Handle<Value> DBWrapper::CompactRange(const Arguments& args) {
HandleScope scope;
if (!args[0]->IsString() || !args[1]->IsString()) {
return scope.Close(Boolean::New(false));
}
switch(args.Length()) {
case 2:
return CompactRangeDefault(args);
case 3:
return args[2]->IsString() ? CompactColumnFamily(args) :
CompactOptions(args);
default:
return CompactAll(args);
}
}
Handle<Value> DBWrapper::Close(const Arguments& args) {
HandleScope scope;
delete ObjectWrap::Unwrap<DBWrapper>(args.This());
return scope.Close(Null());
}