]>
Commit | Line | Data |
---|---|---|
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 | ||
13 | namespace { | |
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 | ||
30 | using namespace v8; | |
31 | ||
32 | ||
33 | Persistent<Function> DBWrapper::constructor; | |
34 | ||
35 | DBWrapper::DBWrapper() { | |
36 | options_.IncreaseParallelism(); | |
37 | options_.OptimizeLevelStyleCompaction(); | |
38 | options_.disable_auto_compactions = true; | |
39 | options_.create_if_missing = true; | |
40 | } | |
41 | ||
42 | DBWrapper::~DBWrapper() { | |
43 | delete db_; | |
44 | } | |
45 | ||
46 | bool DBWrapper::HasFamilyNamed(std::string& name, DBWrapper* db) { | |
47 | return db->columnFamilies_.find(name) != db->columnFamilies_.end(); | |
48 | } | |
49 | ||
50 | ||
51 | void 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 | ||
76 | Handle<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 | ||
130 | Handle<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 | ||
147 | Handle<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 | ||
177 | Handle<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 | ||
205 | Handle<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 | ||
231 | Handle<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 | ||
263 | Handle<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 | 290 | bool 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 | 321 | bool 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 | ||
356 | Handle<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 | ||
412 | Handle<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 | ||
423 | Handle<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 | ||
436 | Handle<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 | ||
468 | Handle<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 | ||
502 | Handle<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 | ||
520 | Handle<Value> DBWrapper::Close(const Arguments& args) { | |
521 | HandleScope scope; | |
522 | ||
523 | delete ObjectWrap::Unwrap<DBWrapper>(args.This()); | |
524 | ||
525 | return scope.Close(Null()); | |
526 | } |