]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/tools/rdb/db_wrapper.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / rocksdb / tools / rdb / db_wrapper.cc
CommitLineData
f67539c2 1// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
7c673cae
FG
2#include <iostream>
3#include <memory>
4#include <vector>
5#include <v8.h>
6#include <node.h>
7
8#include "db/_wrapper.h"
9#include "rocksdb/db.h"
10#include "rocksdb/options.h"
11#include "rocksdb/slice.h"
12
13namespace {
14 void printWithBackSlashes(std::string str) {
15 for (std::string::size_type i = 0; i < str.size(); i++) {
16 if (str[i] == '\\' || str[i] == '"') {
17 std::cout << "\\";
18 }
19
20 std::cout << str[i];
21 }
22 }
23
24 bool has_key_for_array(Local<Object> obj, std::string key) {
25 return obj->Has(String::NewSymbol(key.c_str())) &&
26 obj->Get(String::NewSymbol(key.c_str()))->IsArray();
27 }
28}
29
30using namespace v8;
31
32
33Persistent<Function> DBWrapper::constructor;
34
35DBWrapper::DBWrapper() {
36 options_.IncreaseParallelism();
37 options_.OptimizeLevelStyleCompaction();
38 options_.disable_auto_compactions = true;
39 options_.create_if_missing = true;
40}
41
42DBWrapper::~DBWrapper() {
43 delete db_;
44}
45
46bool DBWrapper::HasFamilyNamed(std::string& name, DBWrapper* db) {
47 return db->columnFamilies_.find(name) != db->columnFamilies_.end();
48}
49
50
51void DBWrapper::Init(Handle<Object> exports) {
52 Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
53 tpl->SetClassName(String::NewSymbol("DBWrapper"));
54 tpl->InstanceTemplate()->SetInternalFieldCount(8);
55 tpl->PrototypeTemplate()->Set(String::NewSymbol("open"),
56 FunctionTemplate::New(Open)->GetFunction());
57 tpl->PrototypeTemplate()->Set(String::NewSymbol("get"),
58 FunctionTemplate::New(Get)->GetFunction());
59 tpl->PrototypeTemplate()->Set(String::NewSymbol("put"),
60 FunctionTemplate::New(Put)->GetFunction());
61 tpl->PrototypeTemplate()->Set(String::NewSymbol("delete"),
62 FunctionTemplate::New(Delete)->GetFunction());
63 tpl->PrototypeTemplate()->Set(String::NewSymbol("dump"),
64 FunctionTemplate::New(Dump)->GetFunction());
65 tpl->PrototypeTemplate()->Set(String::NewSymbol("createColumnFamily"),
66 FunctionTemplate::New(CreateColumnFamily)->GetFunction());
67 tpl->PrototypeTemplate()->Set(String::NewSymbol("writeBatch"),
68 FunctionTemplate::New(WriteBatch)->GetFunction());
69 tpl->PrototypeTemplate()->Set(String::NewSymbol("compactRange"),
70 FunctionTemplate::New(CompactRange)->GetFunction());
71
72 constructor = Persistent<Function>::New(tpl->GetFunction());
73 exports->Set(String::NewSymbol("DBWrapper"), constructor);
74}
75
76Handle<Value> DBWrapper::Open(const Arguments& args) {
77 HandleScope scope;
78 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
79
80 if (!(args[0]->IsString() &&
81 (args[1]->IsUndefined() || args[1]->IsArray()))) {
82 return scope.Close(Boolean::New(false));
83 }
84
85 std::string db_file = *v8::String::Utf8Value(args[0]->ToString());
86
f67539c2 87 std::vector<std::string> cfs = {ROCKSDB_NAMESPACE::kDefaultColumnFamilyName};
7c673cae
FG
88
89 if (!args[1]->IsUndefined()) {
90 Handle<Array> array = Handle<Array>::Cast(args[1]);
91 for (uint i = 0; i < array->Length(); i++) {
92 if (!array->Get(i)->IsString()) {
93 return scope.Close(Boolean::New(false));
94 }
95
96 cfs.push_back(*v8::String::Utf8Value(array->Get(i)->ToString()));
97 }
98 }
99
100 if (cfs.size() == 1) {
f67539c2 101 db_wrapper->status_ = ROCKSDB_NAMESPACE::DB::Open(
7c673cae
FG
102 db_wrapper->options_, db_file, &db_wrapper->db_);
103
104 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
105 }
106
f67539c2 107 std::vector<ROCKSDB_NAMESPACE::ColumnFamilyDescriptor> families;
7c673cae
FG
108
109 for (std::vector<int>::size_type i = 0; i < cfs.size(); i++) {
f67539c2
TL
110 families.push_back(ROCKSDB_NAMESPACE::ColumnFamilyDescriptor(
111 cfs[i], ROCKSDB_NAMESPACE::ColumnFamilyOptions()));
7c673cae
FG
112 }
113
f67539c2
TL
114 std::vector<ROCKSDB_NAMESPACE::ColumnFamilyHandle*> handles;
115 db_wrapper->status_ = ROCKSDB_NAMESPACE::DB::Open(
7c673cae
FG
116 db_wrapper->options_, db_file, families, &handles, &db_wrapper->db_);
117
118 if (!db_wrapper->status_.ok()) {
119 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
120 }
121
122 for (std::vector<int>::size_type i = 0; i < handles.size(); i++) {
123 db_wrapper->columnFamilies_[cfs[i]] = handles[i];
124 }
125
126 return scope.Close(Boolean::New(true));
127}
128
129
130Handle<Value> DBWrapper::New(const Arguments& args) {
131 HandleScope scope;
132 Handle<Value> to_return;
133
134 if (args.IsConstructCall()) {
135 DBWrapper* db_wrapper = new DBWrapper();
136 db_wrapper->Wrap(args.This());
137
138 return args.This();
139 }
140
141 const int argc = 0;
142 Local<Value> argv[0] = {};
143
144 return scope.Close(constructor->NewInstance(argc, argv));
145}
146
147Handle<Value> DBWrapper::Get(const Arguments& args) {
148 HandleScope scope;
149
150 if (!(args[0]->IsString() &&
151 (args[1]->IsUndefined() || args[1]->IsString()))) {
152 return scope.Close(Null());
153 }
154
155 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
156 std::string key = *v8::String::Utf8Value(args[0]->ToString());
157 std::string cf = *v8::String::Utf8Value(args[1]->ToString());
158 std::string value;
159
160 if (args[1]->IsUndefined()) {
f67539c2
TL
161 db_wrapper->status_ =
162 db_wrapper->db_->Get(ROCKSDB_NAMESPACE::ReadOptions(), key, &value);
7c673cae 163 } else if (db_wrapper->HasFamilyNamed(cf, db_wrapper)) {
f67539c2
TL
164 db_wrapper->status_ =
165 db_wrapper->db_->Get(ROCKSDB_NAMESPACE::ReadOptions(),
166 db_wrapper->columnFamilies_[cf], key, &value);
7c673cae
FG
167 } else {
168 return scope.Close(Null());
169 }
170
171 Handle<Value> v = db_wrapper->status_.ok() ?
172 String::NewSymbol(value.c_str()) : Null();
173
174 return scope.Close(v);
175}
176
177Handle<Value> DBWrapper::Put(const Arguments& args) {
178 HandleScope scope;
179
180 if (!(args[0]->IsString() && args[1]->IsString() &&
181 (args[2]->IsUndefined() || args[2]->IsString()))) {
182 return scope.Close(Boolean::New(false));
183 }
184
185 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
186 std::string key = *v8::String::Utf8Value(args[0]->ToString());
187 std::string value = *v8::String::Utf8Value(args[1]->ToString());
188 std::string cf = *v8::String::Utf8Value(args[2]->ToString());
189
190 if (args[2]->IsUndefined()) {
f67539c2
TL
191 db_wrapper->status_ =
192 db_wrapper->db_->Put(ROCKSDB_NAMESPACE::WriteOptions(), key, value);
7c673cae 193 } else if (db_wrapper->HasFamilyNamed(cf, db_wrapper)) {
f67539c2
TL
194 db_wrapper->status_ =
195 db_wrapper->db_->Put(ROCKSDB_NAMESPACE::WriteOptions(),
196 db_wrapper->columnFamilies_[cf], key, value);
7c673cae
FG
197 } else {
198 return scope.Close(Boolean::New(false));
199 }
200
201
202 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
203}
204
205Handle<Value> DBWrapper::Delete(const Arguments& args) {
206 HandleScope scope;
207
208 if (!args[0]->IsString()) {
209 return scope.Close(Boolean::New(false));
210 }
211
212 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
213 std::string arg0 = *v8::String::Utf8Value(args[0]->ToString());
214 std::string arg1 = *v8::String::Utf8Value(args[1]->ToString());
215
216 if (args[1]->IsUndefined()) {
f67539c2
TL
217 db_wrapper->status_ =
218 db_wrapper->db_->Delete(ROCKSDB_NAMESPACE::WriteOptions(), arg0);
7c673cae
FG
219 } else {
220 if (!db_wrapper->HasFamilyNamed(arg1, db_wrapper)) {
221 return scope.Close(Boolean::New(false));
222 }
f67539c2
TL
223 db_wrapper->status_ =
224 db_wrapper->db_->Delete(ROCKSDB_NAMESPACE::WriteOptions(),
225 db_wrapper->columnFamilies_[arg1], arg0);
7c673cae
FG
226 }
227
228 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
229}
230
231Handle<Value> DBWrapper::Dump(const Arguments& args) {
232 HandleScope scope;
f67539c2 233 std::unique_ptr<ROCKSDB_NAMESPACE::Iterator> iterator;
7c673cae
FG
234 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
235 std::string arg0 = *v8::String::Utf8Value(args[0]->ToString());
236
237 if (args[0]->IsUndefined()) {
f67539c2
TL
238 iterator.reset(
239 db_wrapper->db_->NewIterator(ROCKSDB_NAMESPACE::ReadOptions()));
7c673cae
FG
240 } else {
241 if (!db_wrapper->HasFamilyNamed(arg0, db_wrapper)) {
242 return scope.Close(Boolean::New(false));
243 }
244
245 iterator.reset(db_wrapper->db_->NewIterator(
f67539c2 246 ROCKSDB_NAMESPACE::ReadOptions(), db_wrapper->columnFamilies_[arg0]));
7c673cae
FG
247 }
248
249 iterator->SeekToFirst();
250
251 while (iterator->Valid()) {
252 std::cout << "\"";
253 printWithBackSlashes(iterator->key().ToString());
254 std::cout << "\" => \"";
255 printWithBackSlashes(iterator->value().ToString());
256 std::cout << "\"\n";
257 iterator->Next();
258 }
259
260 return scope.Close(Boolean::New(true));
261}
262
263Handle<Value> DBWrapper::CreateColumnFamily(const Arguments& args) {
264 HandleScope scope;
265
266 if (!args[0]->IsString()) {
267 return scope.Close(Boolean::New(false));
268 }
269
270 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
271 std::string cf_name = *v8::String::Utf8Value(args[0]->ToString());
272
273 if (db_wrapper->HasFamilyNamed(cf_name, db_wrapper)) {
274 return scope.Close(Boolean::New(false));
275 }
276
f67539c2 277 ROCKSDB_NAMESPACE::ColumnFamilyHandle* cf;
7c673cae 278 db_wrapper->status_ = db_wrapper->db_->CreateColumnFamily(
f67539c2 279 ROCKSDB_NAMESPACE::ColumnFamilyOptions(), cf_name, &cf);
7c673cae
FG
280
281 if (!db_wrapper->status_.ok()) {
282 return scope.Close(Boolean::New(false));
283 }
284
285 db_wrapper->columnFamilies_[cf_name] = cf;
286
287 return scope.Close(Boolean::New(true));
288}
289
f67539c2 290bool DBWrapper::AddToBatch(ROCKSDB_NAMESPACE::WriteBatch& batch, bool del,
7c673cae
FG
291 Handle<Array> array) {
292 Handle<Array> put_pair;
293 for (uint i = 0; i < array->Length(); i++) {
294 if (del) {
295 if (!array->Get(i)->IsString()) {
296 return false;
297 }
298
299 batch.Delete(*v8::String::Utf8Value(array->Get(i)->ToString()));
300 continue;
301 }
302
303 if (!array->Get(i)->IsArray()) {
304 return false;
305 }
306
307 put_pair = Handle<Array>::Cast(array->Get(i));
308
309 if (!put_pair->Get(0)->IsString() || !put_pair->Get(1)->IsString()) {
310 return false;
311 }
312
313 batch.Put(
314 *v8::String::Utf8Value(put_pair->Get(0)->ToString()),
315 *v8::String::Utf8Value(put_pair->Get(1)->ToString()));
316 }
317
318 return true;
319}
320
f67539c2 321bool DBWrapper::AddToBatch(ROCKSDB_NAMESPACE::WriteBatch& batch, bool del,
7c673cae
FG
322 Handle<Array> array, DBWrapper* db_wrapper,
323 std::string cf) {
324 Handle<Array> put_pair;
325 for (uint i = 0; i < array->Length(); i++) {
326 if (del) {
327 if (!array->Get(i)->IsString()) {
328 return false;
329 }
330
331 batch.Delete(
332 db_wrapper->columnFamilies_[cf],
333 *v8::String::Utf8Value(array->Get(i)->ToString()));
334 continue;
335 }
336
337 if (!array->Get(i)->IsArray()) {
338 return false;
339 }
340
341 put_pair = Handle<Array>::Cast(array->Get(i));
342
343 if (!put_pair->Get(0)->IsString() || !put_pair->Get(1)->IsString()) {
344 return false;
345 }
346
347 batch.Put(
348 db_wrapper->columnFamilies_[cf],
349 *v8::String::Utf8Value(put_pair->Get(0)->ToString()),
350 *v8::String::Utf8Value(put_pair->Get(1)->ToString()));
351 }
352
353 return true;
354}
355
356Handle<Value> DBWrapper::WriteBatch(const Arguments& args) {
357 HandleScope scope;
358
359 if (!args[0]->IsArray()) {
360 return scope.Close(Boolean::New(false));
361 }
362
363 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
364 Handle<Array> sub_batches = Handle<Array>::Cast(args[0]);
365 Local<Object> sub_batch;
f67539c2 366 ROCKSDB_NAMESPACE::WriteBatch batch;
7c673cae
FG
367 bool well_formed;
368
369 for (uint i = 0; i < sub_batches->Length(); i++) {
370 if (!sub_batches->Get(i)->IsObject()) {
371 return scope.Close(Boolean::New(false));
372 }
373 sub_batch = sub_batches->Get(i)->ToObject();
374
375 if (sub_batch->Has(String::NewSymbol("column_family"))) {
376 if (!has_key_for_array(sub_batch, "put") &&
377 !has_key_for_array(sub_batch, "delete")) {
378 return scope.Close(Boolean::New(false));
379 }
380
381 well_formed = db_wrapper->AddToBatch(
382 batch, false,
383 Handle<Array>::Cast(sub_batch->Get(String::NewSymbol("put"))),
384 db_wrapper, *v8::String::Utf8Value(sub_batch->Get(
385 String::NewSymbol("column_family"))));
386
387 well_formed = db_wrapper->AddToBatch(
388 batch, true,
389 Handle<Array>::Cast(sub_batch->Get(String::NewSymbol("delete"))),
390 db_wrapper, *v8::String::Utf8Value(sub_batch->Get(
391 String::NewSymbol("column_family"))));
392 } else {
393 well_formed = db_wrapper->AddToBatch(
394 batch, false,
395 Handle<Array>::Cast(sub_batch->Get(String::NewSymbol("put"))));
396 well_formed = db_wrapper->AddToBatch(
397 batch, true,
398 Handle<Array>::Cast(sub_batch->Get(String::NewSymbol("delete"))));
399
400 if (!well_formed) {
401 return scope.Close(Boolean::New(false));
402 }
403 }
404 }
405
f67539c2
TL
406 db_wrapper->status_ =
407 db_wrapper->db_->Write(ROCKSDB_NAMESPACE::WriteOptions(), &batch);
7c673cae
FG
408
409 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
410}
411
412Handle<Value> DBWrapper::CompactRangeDefault(const Arguments& args) {
413 HandleScope scope;
414
415 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
f67539c2
TL
416 ROCKSDB_NAMESPACE::Slice begin = *v8::String::Utf8Value(args[0]->ToString());
417 ROCKSDB_NAMESPACE::Slice end = *v8::String::Utf8Value(args[1]->ToString());
7c673cae
FG
418 db_wrapper->status_ = db_wrapper->db_->CompactRange(&end, &begin);
419
420 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
421}
422
423Handle<Value> DBWrapper::CompactColumnFamily(const Arguments& args) {
424 HandleScope scope;
425
426 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
f67539c2
TL
427 ROCKSDB_NAMESPACE::Slice begin = *v8::String::Utf8Value(args[0]->ToString());
428 ROCKSDB_NAMESPACE::Slice end = *v8::String::Utf8Value(args[1]->ToString());
7c673cae
FG
429 std::string cf = *v8::String::Utf8Value(args[2]->ToString());
430 db_wrapper->status_ = db_wrapper->db_->CompactRange(
431 db_wrapper->columnFamilies_[cf], &begin, &end);
432
433 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
434}
435
436Handle<Value> DBWrapper::CompactOptions(const Arguments& args) {
437 HandleScope scope;
438
439 if (!args[2]->IsObject()) {
440 return scope.Close(Boolean::New(false));
441 }
442
443 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
f67539c2
TL
444 ROCKSDB_NAMESPACE::Slice begin = *v8::String::Utf8Value(args[0]->ToString());
445 ROCKSDB_NAMESPACE::Slice end = *v8::String::Utf8Value(args[1]->ToString());
7c673cae
FG
446 Local<Object> options = args[2]->ToObject();
447 int target_level = -1, target_path_id = 0;
448
449 if (options->Has(String::NewSymbol("target_level")) &&
450 options->Get(String::NewSymbol("target_level"))->IsInt32()) {
451 target_level = (int)(options->Get(
452 String::NewSymbol("target_level"))->ToInt32()->Value());
453
454 if (options->Has(String::NewSymbol("target_path_id")) ||
455 options->Get(String::NewSymbol("target_path_id"))->IsInt32()) {
456 target_path_id = (int)(options->Get(
457 String::NewSymbol("target_path_id"))->ToInt32()->Value());
458 }
459 }
460
461 db_wrapper->status_ = db_wrapper->db_->CompactRange(
462 &begin, &end, true, target_level, target_path_id
463 );
464
465 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
466}
467
468Handle<Value> DBWrapper::CompactAll(const Arguments& args) {
469 HandleScope scope;
470
471 if (!args[2]->IsObject() || !args[3]->IsString()) {
472 return scope.Close(Boolean::New(false));
473 }
474
475 DBWrapper* db_wrapper = ObjectWrap::Unwrap<DBWrapper>(args.This());
f67539c2
TL
476 ROCKSDB_NAMESPACE::Slice begin = *v8::String::Utf8Value(args[0]->ToString());
477 ROCKSDB_NAMESPACE::Slice end = *v8::String::Utf8Value(args[1]->ToString());
7c673cae
FG
478 Local<Object> options = args[2]->ToObject();
479 std::string cf = *v8::String::Utf8Value(args[3]->ToString());
480
481 int target_level = -1, target_path_id = 0;
482
483 if (options->Has(String::NewSymbol("target_level")) &&
484 options->Get(String::NewSymbol("target_level"))->IsInt32()) {
485 target_level = (int)(options->Get(
486 String::NewSymbol("target_level"))->ToInt32()->Value());
487
488 if (options->Has(String::NewSymbol("target_path_id")) ||
489 options->Get(String::NewSymbol("target_path_id"))->IsInt32()) {
490 target_path_id = (int)(options->Get(
491 String::NewSymbol("target_path_id"))->ToInt32()->Value());
492 }
493 }
494
495 db_wrapper->status_ = db_wrapper->db_->CompactRange(
496 db_wrapper->columnFamilies_[cf], &begin, &end, true, target_level,
497 target_path_id);
498
499 return scope.Close(Boolean::New(db_wrapper->status_.ok()));
500}
501
502Handle<Value> DBWrapper::CompactRange(const Arguments& args) {
503 HandleScope scope;
504
505 if (!args[0]->IsString() || !args[1]->IsString()) {
506 return scope.Close(Boolean::New(false));
507 }
508
509 switch(args.Length()) {
510 case 2:
511 return CompactRangeDefault(args);
512 case 3:
513 return args[2]->IsString() ? CompactColumnFamily(args) :
514 CompactOptions(args);
515 default:
516 return CompactAll(args);
517 }
518}
519
520Handle<Value> DBWrapper::Close(const Arguments& args) {
521 HandleScope scope;
522
523 delete ObjectWrap::Unwrap<DBWrapper>(args.This());
524
525 return scope.Close(Null());
526}