github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb.chai2010/capi/leveldb_c.cc (about) 1 // Copyright 2013 <chaishushan{AT}gmail.com>. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "leveldb_c.h" 6 7 #include "leveldb/cache.h" 8 #include "leveldb/comparator.h" 9 #include "leveldb/db.h" 10 #include "leveldb/filter_policy.h" 11 #include "leveldb/iterator.h" 12 #include "leveldb/options.h" 13 #include "leveldb/status.h" 14 #include "leveldb/write_batch.h" 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <vector> 19 20 // ---------------------------------------------------------------------------- 21 // Utils 22 // ---------------------------------------------------------------------------- 23 24 #define DISABLE_NEW_AND_DELETE(TypeName) private: \ 25 TypeName(); \ 26 TypeName(const TypeName&); \ 27 TypeName& operator=(const TypeName&); \ 28 ~TypeName() 29 30 inline leveldb_bool_t fromStdBool(bool v) { 31 return (v)? 1: 0; 32 } 33 34 inline bool toStdBool(leveldb_bool_t v) { 35 return (v != 0)? true: false; 36 } 37 38 inline leveldb_slice_t fromLdbSlice(const leveldb::Slice& a) { 39 return leveldb_slice(a.data(), int32_t(a.size())); 40 } 41 42 inline leveldb::Slice toLdbSlice(const leveldb_slice_t* a) { 43 if(a != NULL && a->data != NULL && a->size > 0) { 44 return leveldb::Slice(a->data, size_t(a->size)); 45 } else { 46 return leveldb::Slice(NULL, 0); 47 } 48 } 49 50 inline leveldb_status_t fromLdbStatus(const leveldb::Status& s, leveldb_value_t** err) { 51 if(s.ok()) { 52 return leveldb_status_ok; 53 } 54 if(err != NULL && *err != NULL) { 55 if(*err != NULL) { leveldb_value_destroy(*err); } 56 std::string tmp = s.ToString(); 57 *err = leveldb_value_create(tmp.data(), int32_t(tmp.size())); 58 } 59 if(s.IsNotFound()) { 60 return leveldb_status_not_found; 61 } 62 if(s.IsCorruption()) { 63 return leveldb_status_corruption; 64 } 65 if(s.IsIOError()) { 66 return leveldb_status_io_error; 67 } 68 return leveldb_status_unknown; 69 } 70 71 // ---------------------------------------------------------------------------- 72 // Version 73 // ---------------------------------------------------------------------------- 74 75 int32_t leveldb_major_version() { 76 return int32_t(leveldb::kMajorVersion); 77 } 78 79 int32_t leveldb_minor_version() { 80 return int32_t(leveldb::kMinorVersion); 81 } 82 83 // ---------------------------------------------------------------------------- 84 // Slice 85 // ---------------------------------------------------------------------------- 86 87 leveldb_slice_t leveldb_slice(const char* data, int32_t size) { 88 if(data != NULL && size > 0) { 89 leveldb_slice_t a = { data, size }; 90 return a; 91 } else { 92 leveldb_slice_t a = { NULL, 0 }; 93 return a; 94 } 95 } 96 97 // ---------------------------------------------------------------------------- 98 // Value 99 // ---------------------------------------------------------------------------- 100 101 struct leveldb_value_t { 102 std::string value_; 103 leveldb_value_t(const char* data, int32_t size): value_(data, size) {} 104 leveldb_value_t(const std::string& data): value_(data) {} 105 }; 106 107 leveldb_value_t* leveldb_value_create(const char*data, int32_t size) { 108 if(data != NULL && size > 0) { 109 leveldb_value_t* slice = new leveldb_value_t(data, size); 110 return slice; 111 } else { 112 leveldb_value_t* slice = new leveldb_value_t(NULL, 0); 113 return slice; 114 } 115 } 116 leveldb_value_t* leveldb_value_create_copy( 117 leveldb_value_t* value 118 ) { 119 if(value != NULL) { 120 return leveldb_value_create( 121 value->value_.data(), 122 int32_t(value->value_.size()) 123 ); 124 } else { 125 return leveldb_value_create(NULL, 0); 126 } 127 } 128 void leveldb_value_destroy(leveldb_value_t* value) { 129 if(value != NULL) { 130 delete value; 131 } 132 } 133 134 int32_t leveldb_value_size(const leveldb_value_t* value) { 135 if(value != NULL && !value->value_.empty()) { 136 return int32_t(value->value_.size()); 137 } else { 138 return 0; 139 } 140 } 141 142 const char* leveldb_value_data(const leveldb_value_t* value) { 143 if(value != NULL && !value->value_.empty()) { 144 return value->value_.data(); 145 } else { 146 return NULL; 147 } 148 } 149 150 const char* leveldb_value_cstr(const leveldb_value_t* value) { 151 if(value != NULL && !value->value_.empty()) { 152 return value->value_.data(); 153 } else { 154 return NULL; 155 } 156 } 157 158 // ---------------------------------------------------------------------------- 159 // Options 160 // ---------------------------------------------------------------------------- 161 162 struct leveldb_options_t: leveldb::Options { 163 DISABLE_NEW_AND_DELETE(leveldb_options_t); 164 }; 165 166 leveldb_options_t* leveldb_options_create() { 167 return (leveldb_options_t*)(new leveldb::Options()); 168 } 169 170 void leveldb_options_destroy(leveldb_options_t* opt) { 171 if(opt != NULL) { 172 delete (leveldb::Options*)opt; 173 } 174 } 175 176 void leveldb_options_set_comparator( 177 leveldb_options_t* opt, 178 leveldb_comparator_t* cmp 179 ) { 180 if(opt != NULL) { 181 opt->comparator = (leveldb::Comparator*)(cmp); 182 } 183 } 184 185 leveldb_comparator_t* leveldb_options_get_comparator( 186 leveldb_options_t* opt 187 ) { 188 if(opt != NULL) { 189 return (leveldb_comparator_t*)(opt->comparator); 190 } else { 191 return NULL; 192 } 193 } 194 195 void leveldb_options_set_filter_policy( 196 leveldb_options_t* opt, 197 leveldb_filterpolicy_t* policy 198 ) { 199 if(opt != NULL) { 200 opt->filter_policy = (leveldb::FilterPolicy*)(policy); 201 } 202 } 203 leveldb_filterpolicy_t* leveldb_options_get_filter_policy( 204 leveldb_options_t* opt 205 ) { 206 if(opt != NULL) { 207 return (leveldb_filterpolicy_t*)(opt->filter_policy); 208 } else { 209 return NULL; 210 } 211 } 212 213 void leveldb_options_set_create_if_missing( 214 leveldb_options_t* opt, leveldb_bool_t v 215 ) { 216 if(opt != NULL) { 217 opt->create_if_missing = toStdBool(v); 218 } 219 } 220 leveldb_bool_t leveldb_options_get_create_if_missing( 221 leveldb_options_t* opt 222 ) { 223 if(opt != NULL) { 224 return fromStdBool(opt->create_if_missing); 225 } else { 226 return fromStdBool(false); 227 } 228 } 229 230 void leveldb_options_set_error_if_exists( 231 leveldb_options_t* opt, leveldb_bool_t v 232 ) { 233 if(opt != NULL) { 234 opt->error_if_exists = toStdBool(v); 235 } 236 } 237 leveldb_bool_t leveldb_options_get_error_if_exists( 238 leveldb_options_t* opt 239 ) { 240 if(opt != NULL) { 241 return fromStdBool(opt->error_if_exists); 242 } else { 243 return fromStdBool(false); 244 } 245 } 246 247 void leveldb_options_set_paranoid_checks( 248 leveldb_options_t* opt, leveldb_bool_t v 249 ) { 250 if(opt != NULL) { 251 opt->paranoid_checks = toStdBool(v); 252 } 253 } 254 leveldb_bool_t leveldb_options_get_paranoid_checks( 255 leveldb_options_t* opt 256 ) { 257 if(opt != NULL) { 258 return fromStdBool(opt->paranoid_checks); 259 } else { 260 return fromStdBool(false); 261 } 262 } 263 264 void leveldb_options_set_write_buffer_size( 265 leveldb_options_t* opt, int32_t size 266 ) { 267 if(opt != NULL) { 268 opt->write_buffer_size = size_t(size); 269 } 270 } 271 int32_t leveldb_options_get_write_buffer_size( 272 leveldb_options_t* opt 273 ) { 274 if(opt != NULL) { 275 return int32_t(opt->write_buffer_size); 276 } else { 277 return int32_t(0); 278 } 279 } 280 281 void leveldb_options_set_max_open_files(leveldb_options_t* opt, int32_t n) { 282 if(opt != NULL) { 283 opt->max_open_files = n; 284 } 285 } 286 int32_t leveldb_options_get_max_open_files( 287 leveldb_options_t* opt 288 ) { 289 if(opt != NULL) { 290 return int32_t(opt->max_open_files); 291 } else { 292 return int32_t(0); 293 } 294 } 295 296 void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) { 297 if(opt != NULL) { 298 opt->block_cache = (leveldb::Cache*)(c); 299 } 300 } 301 leveldb_cache_t* leveldb_options_get_cache( 302 leveldb_options_t* opt 303 ) { 304 if(opt != NULL) { 305 return (leveldb_cache_t*)(opt->block_cache); 306 } else { 307 return NULL; 308 } 309 } 310 311 void leveldb_options_set_block_size(leveldb_options_t* opt, int32_t size) { 312 if(opt != NULL) { 313 opt->block_size = size_t(size); 314 } 315 } 316 int32_t leveldb_options_get_block_size( 317 leveldb_options_t* opt 318 ) { 319 if(opt != NULL) { 320 return int32_t(opt->block_size); 321 } else { 322 return int32_t(0); 323 } 324 } 325 326 void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int32_t n) { 327 if(opt != NULL) { 328 opt->block_restart_interval = int32_t(n); 329 } 330 } 331 int32_t leveldb_options_get_block_restart_interval( 332 leveldb_options_t* opt 333 ) { 334 if(opt != NULL) { 335 return int32_t(opt->block_restart_interval); 336 } else { 337 return int32_t(0); 338 } 339 } 340 341 void leveldb_options_set_compression( 342 leveldb_options_t* opt, 343 leveldb_compression_t t 344 ) { 345 if(opt != NULL) { 346 opt->compression = static_cast<leveldb::CompressionType>(t); 347 } 348 } 349 leveldb_compression_t leveldb_options_get_compression( 350 leveldb_options_t* opt 351 ) { 352 if(opt != NULL) { 353 return leveldb_compression_t(opt->compression); 354 } else { 355 return leveldb_compression_t(leveldb_compression_nil); 356 } 357 } 358 359 // ---------------------------------------------------------------------------- 360 // ReadOptions 361 // ---------------------------------------------------------------------------- 362 363 struct leveldb_readoptions_t: leveldb::ReadOptions { 364 DISABLE_NEW_AND_DELETE(leveldb_readoptions_t); 365 }; 366 367 leveldb_readoptions_t* leveldb_readoptions_create() { 368 return (leveldb_readoptions_t*)(new leveldb::ReadOptions()); 369 } 370 371 void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { 372 if(opt != NULL) { 373 delete (leveldb::ReadOptions*)opt; 374 } 375 } 376 377 void leveldb_readoptions_set_verify_checksums( 378 leveldb_readoptions_t* opt, 379 leveldb_bool_t v 380 ) { 381 if(opt != NULL) { 382 opt->verify_checksums = toStdBool(v); 383 } 384 } 385 386 leveldb_bool_t leveldb_readoptions_get_verify_checksums( 387 leveldb_readoptions_t* opt 388 ) { 389 if(opt != NULL) { 390 return fromStdBool(opt->verify_checksums); 391 } else { 392 return fromStdBool(false); 393 } 394 } 395 396 void leveldb_readoptions_set_fill_cache( 397 leveldb_readoptions_t* opt, leveldb_bool_t v 398 ) { 399 if(opt != NULL) { 400 opt->fill_cache = toStdBool(v); 401 } 402 } 403 404 leveldb_bool_t leveldb_readoptions_get_fill_cache( 405 leveldb_readoptions_t* opt 406 ) { 407 if(opt != NULL) { 408 return fromStdBool(opt->fill_cache); 409 } else { 410 return fromStdBool(false); 411 } 412 } 413 414 void leveldb_readoptions_set_snapshot( 415 leveldb_readoptions_t* opt, 416 const leveldb_snapshot_t* snap 417 ) { 418 if(opt != NULL) { 419 opt->snapshot = (leveldb::Snapshot*)(snap); 420 } 421 } 422 423 leveldb_snapshot_t* leveldb_readoptions_get_snapshot( 424 leveldb_readoptions_t* opt 425 ) { 426 if(opt != NULL) { 427 return (leveldb_snapshot_t*)(opt->snapshot); 428 } else { 429 return NULL; 430 } 431 } 432 433 // ---------------------------------------------------------------------------- 434 // WriteOptions 435 // ---------------------------------------------------------------------------- 436 437 struct leveldb_writeoptions_t: leveldb::WriteOptions { 438 DISABLE_NEW_AND_DELETE(leveldb_writeoptions_t); 439 }; 440 441 leveldb_writeoptions_t* leveldb_writeoptions_create() { 442 return (leveldb_writeoptions_t*)(new leveldb::WriteOptions()); 443 } 444 445 void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { 446 if(opt != NULL) { 447 delete (leveldb::WriteOptions*)opt; 448 } 449 } 450 451 void leveldb_writeoptions_set_sync( 452 leveldb_writeoptions_t* opt, leveldb_bool_t v 453 ) { 454 if(opt != NULL) { 455 opt->sync = toStdBool(v); 456 } 457 } 458 459 leveldb_bool_t leveldb_writeoptions_get_sync(leveldb_writeoptions_t* opt) { 460 if(opt != NULL) { 461 return fromStdBool(opt->sync); 462 } else { 463 return fromStdBool(false); 464 } 465 } 466 467 // ---------------------------------------------------------------------------- 468 // DB 469 // ---------------------------------------------------------------------------- 470 471 struct leveldb_t: leveldb::DB { 472 DISABLE_NEW_AND_DELETE(leveldb_t); 473 }; 474 struct leveldb_snapshot_t: leveldb::Snapshot { 475 DISABLE_NEW_AND_DELETE(leveldb_snapshot_t); 476 }; 477 478 leveldb_status_t leveldb_repair_db( 479 const leveldb_options_t* opt, 480 const char* name, 481 leveldb_value_t** errptr 482 ) { 483 if(name == NULL || name[0] == '\0') { 484 return leveldb_status_invalid_argument; 485 } 486 leveldb::Status s = RepairDB(name, 487 (opt!=NULL)? *(leveldb::Options*)(opt): leveldb::Options() 488 ); 489 return fromLdbStatus(s, errptr); 490 } 491 leveldb_status_t leveldb_destroy_db( 492 const leveldb_options_t* opt, 493 const char* name, 494 leveldb_value_t** errptr 495 ) { 496 if(name == NULL || name[0] == '\0') { 497 return leveldb_status_invalid_argument; 498 } 499 leveldb::Status s = DestroyDB(name, 500 (opt!=NULL)? *(leveldb::Options*)(opt): leveldb::Options() 501 ); 502 return fromLdbStatus(s, errptr); 503 } 504 505 leveldb_status_t leveldb_open( 506 const leveldb_options_t* opt, 507 const char* name, 508 leveldb_t** db, 509 leveldb_value_t** errptr 510 ) { 511 if(name == NULL || name[0] == '\0' || db == NULL || *db == NULL) { 512 return leveldb_status_invalid_argument; 513 } 514 leveldb::Status s = leveldb::DB::Open( 515 (opt!=NULL)? *(leveldb::Options*)(opt): leveldb::Options(), 516 std::string(name), 517 (leveldb::DB**)db 518 ); 519 return fromLdbStatus(s, errptr); 520 } 521 522 void leveldb_close(leveldb_t* db) { 523 if(db != NULL) { 524 delete (leveldb::DB*)db; 525 } 526 } 527 528 leveldb_status_t leveldb_get( 529 leveldb_t* db, 530 const leveldb_readoptions_t* opt, 531 const leveldb_slice_t* key, 532 leveldb_value_t** value, 533 leveldb_value_t** errptr 534 ) { 535 if(db == NULL|| key == NULL|| value == NULL|| *value == NULL) { 536 return leveldb_status_invalid_argument; 537 } 538 std::string tmp; 539 leveldb::Status s = db->Get( 540 (opt!=NULL)? *(leveldb::ReadOptions*)(opt): leveldb::ReadOptions(), 541 toLdbSlice(key), 542 &tmp 543 ); 544 *value = leveldb_value_create(tmp.data(), int32_t(tmp.size())); 545 return fromLdbStatus(s, errptr); 546 } 547 548 leveldb_status_t leveldb_put( 549 leveldb_t* db, 550 const leveldb_writeoptions_t* opt, 551 const leveldb_slice_t* key, 552 const leveldb_slice_t* val, 553 leveldb_value_t** errptr 554 ) { 555 if(db == NULL || key == NULL) { 556 return leveldb_status_invalid_argument; 557 } 558 leveldb::Status s = db->Put( 559 (opt!=NULL)? *(leveldb::WriteOptions*)(opt): leveldb::WriteOptions(), 560 toLdbSlice(key), 561 toLdbSlice(val) 562 ); 563 return fromLdbStatus(s, errptr); 564 } 565 566 leveldb_status_t leveldb_delete( 567 leveldb_t* db, 568 const leveldb_writeoptions_t* opt, 569 const leveldb_slice_t* key, 570 leveldb_value_t** errptr 571 ) { 572 if(db == NULL || key == NULL) { 573 return leveldb_status_invalid_argument; 574 } 575 leveldb::Status s = db->Delete( 576 (opt!=NULL)? *(leveldb::WriteOptions*)(opt): leveldb::WriteOptions(), 577 toLdbSlice(key) 578 ); 579 return fromLdbStatus(s, errptr); 580 } 581 582 leveldb_status_t leveldb_write( 583 leveldb_t* db, 584 const leveldb_writeoptions_t* opt, 585 leveldb_writebatch_t* batch, 586 leveldb_value_t** errptr 587 ) { 588 if(db == NULL || batch == NULL) { 589 return leveldb_status_invalid_argument; 590 } 591 leveldb::Status s = db->Write( 592 (opt!=NULL)? *(leveldb::WriteOptions*)(opt): leveldb::WriteOptions(), 593 (leveldb::WriteBatch*)batch 594 ); 595 return fromLdbStatus(s, errptr); 596 } 597 598 leveldb_bool_t leveldb_property_value( 599 leveldb_t* db, 600 const char* propname, 601 leveldb_value_t** value 602 ) { 603 if(db == NULL) { 604 return fromStdBool(false); 605 } 606 if(propname == NULL || propname[0] == '\0') { 607 return fromStdBool(false); 608 } 609 if(value == NULL || *value == NULL) { 610 return fromStdBool(false); 611 } 612 std::string tmp; 613 if (db->GetProperty(leveldb::Slice(propname), &tmp)) { 614 *value = leveldb_value_create(tmp.data(), int32_t(tmp.size())); 615 return fromStdBool(true); 616 } else { 617 return fromStdBool(false); 618 } 619 } 620 621 void leveldb_approximate_sizes( 622 leveldb_t* db, 623 int32_t num_ranges, 624 const leveldb_slice_t* range_start_key[], 625 const leveldb_slice_t* range_limit_key[], 626 uint64_t sizes[] 627 ) { 628 if(db == NULL || num_ranges <= 0) { 629 return; 630 } 631 if(range_start_key == NULL || range_limit_key == NULL || sizes == NULL) { 632 return; 633 } 634 leveldb::Range* ranges = new leveldb::Range[num_ranges]; 635 for (int32_t i = 0; i < num_ranges; i++) { 636 ranges[i].start = toLdbSlice(range_start_key[i]); 637 ranges[i].limit = toLdbSlice(range_limit_key[i]); 638 } 639 db->GetApproximateSizes(ranges, num_ranges, sizes); 640 delete[] ranges; 641 } 642 643 void leveldb_compact_range( 644 leveldb_t* db, 645 const leveldb_slice_t* range_start_key, 646 const leveldb_slice_t* range_limit_key 647 ) { 648 if(db == NULL) return; 649 leveldb::Slice a = toLdbSlice(range_start_key); 650 leveldb::Slice b = toLdbSlice(range_limit_key); 651 db->CompactRange(&a, &b); 652 } 653 654 const leveldb_snapshot_t* leveldb_create_snapshot( 655 leveldb_t* db 656 ) { 657 if(db != NULL) { 658 return (leveldb_snapshot_t*)(db->GetSnapshot()); 659 } else { 660 return NULL; 661 } 662 } 663 664 void leveldb_release_snapshot( 665 leveldb_t* db, 666 const leveldb_snapshot_t* snapshot 667 ) { 668 if(db != NULL && snapshot != NULL) { 669 db->ReleaseSnapshot((leveldb::Snapshot*)(snapshot)); 670 } 671 } 672 673 // ---------------------------------------------------------------------------- 674 // Iterator 675 // ---------------------------------------------------------------------------- 676 677 struct leveldb_iterator_t: leveldb::Iterator { 678 DISABLE_NEW_AND_DELETE(leveldb_iterator_t); 679 }; 680 681 leveldb_iterator_t* leveldb_create_iterator( 682 leveldb_t* db, 683 const leveldb_readoptions_t* opt 684 ) { 685 if(db != NULL) { 686 return (leveldb_iterator_t*)(db->NewIterator( 687 (opt!=NULL)? *(leveldb::ReadOptions*)(opt): leveldb::ReadOptions() 688 )); 689 } else { 690 return NULL; 691 } 692 } 693 694 void leveldb_iter_destroy( 695 leveldb_iterator_t* it 696 ) { 697 if(it != NULL) { 698 delete (leveldb::Iterator*)it; 699 } 700 } 701 702 leveldb_bool_t leveldb_iter_valid(const leveldb_iterator_t* it) { 703 if(it != NULL) { 704 return fromStdBool(it->Valid()); 705 } else { 706 return fromStdBool(false); 707 } 708 } 709 710 void leveldb_iter_seek_to_first( 711 leveldb_iterator_t* it 712 ) { 713 if(it != NULL) { 714 it->SeekToFirst(); 715 } 716 } 717 718 void leveldb_iter_seek_to_last( 719 leveldb_iterator_t* it 720 ) { 721 it->SeekToLast(); 722 } 723 724 void leveldb_iter_seek( 725 leveldb_iterator_t* it, 726 const leveldb_slice_t* key 727 ) { 728 if(it != NULL) { 729 it->Seek(toLdbSlice(key)); 730 } 731 } 732 733 void leveldb_iter_next(leveldb_iterator_t* it) { 734 if(it != NULL) it->Next(); 735 } 736 737 void leveldb_iter_prev(leveldb_iterator_t* it) { 738 if(it != NULL) it->Prev(); 739 } 740 741 leveldb_slice_t leveldb_iter_key(const leveldb_iterator_t* it) { 742 if(it != NULL) { 743 leveldb::Slice s = it->key(); 744 return leveldb_slice(s.data(), int32_t(s.size())); 745 } else { 746 return leveldb_slice(NULL, int32_t(0)); 747 } 748 } 749 750 leveldb_slice_t leveldb_iter_value(const leveldb_iterator_t* it) { 751 if(it != NULL) { 752 leveldb::Slice s = it->value(); 753 return leveldb_slice(s.data(), int32_t(s.size())); 754 } else { 755 return leveldb_slice(NULL, int32_t(0)); 756 } 757 } 758 759 leveldb_status_t leveldb_iter_get_error(const leveldb_iterator_t* it, 760 leveldb_value_t** errptr 761 ) { 762 if(it == NULL) { 763 return leveldb_status_invalid_argument; 764 } 765 leveldb::Status s = it->status(); 766 return fromLdbStatus(s, errptr); 767 } 768 769 // ---------------------------------------------------------------------------- 770 // WriteBatch 771 // ---------------------------------------------------------------------------- 772 773 struct leveldb_writebatch_t: leveldb::WriteBatch { 774 DISABLE_NEW_AND_DELETE(leveldb_writebatch_t); 775 }; 776 777 leveldb_writebatch_t* leveldb_writebatch_create() { 778 return (leveldb_writebatch_t*)(new leveldb::WriteBatch()); 779 } 780 781 void leveldb_writebatch_destroy(leveldb_writebatch_t* batch) { 782 if(batch != NULL) { 783 delete (leveldb::WriteBatch*)batch; 784 } 785 } 786 787 void leveldb_writebatch_put( 788 leveldb_writebatch_t* batch, 789 const leveldb_slice_t* key, 790 const leveldb_slice_t* val 791 ) { 792 if(batch != NULL && key != NULL) { 793 batch->Put(toLdbSlice(key), toLdbSlice(val)); 794 } 795 } 796 void leveldb_writebatch_delete( 797 leveldb_writebatch_t* batch, 798 const leveldb_slice_t* key 799 ) { 800 if(batch != NULL && key != NULL) { 801 batch->Delete(toLdbSlice(key)); 802 } 803 } 804 void leveldb_writebatch_clear(leveldb_writebatch_t* batch) { 805 if(batch != NULL) { 806 batch->Clear(); 807 } 808 } 809 810 void leveldb_writebatch_iterate( 811 leveldb_writebatch_t* batch, 812 void* state, 813 void (*put)( 814 void* state, 815 const leveldb_slice_t* k, 816 const leveldb_slice_t* v 817 ), 818 void (*deleted)( 819 void* state, 820 const leveldb_slice_t* k 821 ) 822 ) { 823 if(batch == NULL) return; 824 struct H: public leveldb::WriteBatch::Handler { 825 void* state_; 826 void (*put_)( 827 void*, const leveldb_slice_t* k, const leveldb_slice_t* v 828 ); 829 void (*deleted_)(void*, const leveldb_slice_t* k); 830 831 virtual void Put( 832 const leveldb::Slice& key, const leveldb::Slice& val 833 ) { 834 if(put_ != NULL) { 835 leveldb_slice_t k = fromLdbSlice(key); 836 leveldb_slice_t v = fromLdbSlice(val); 837 (*put_)(state_, &k, &v); 838 } 839 } 840 virtual void Delete(const leveldb::Slice& key) { 841 if(deleted_ != NULL) { 842 leveldb_slice_t k = fromLdbSlice(key); 843 (*deleted_)(state_, &k); 844 } 845 } 846 }; 847 H handler; 848 handler.state_ = state; 849 handler.put_ = put; 850 handler.deleted_ = deleted; 851 batch->Iterate(&handler); 852 } 853 854 // ---------------------------------------------------------------------------- 855 // Comparator 856 // ---------------------------------------------------------------------------- 857 858 struct leveldb_comparator_t : public leveldb::Comparator { 859 void* state_; 860 void (*destructor_)(void*); 861 int32_t (*compare_)( 862 void* state, 863 const leveldb_slice_t* a, 864 const leveldb_slice_t* b 865 ); 866 const char* (*name_)(void*); 867 868 virtual ~leveldb_comparator_t() { 869 (*destructor_)(state_); 870 } 871 872 virtual int32_t Compare( 873 const leveldb::Slice& a, const leveldb::Slice& b 874 ) const { 875 leveldb_slice_t a_ = fromLdbSlice(a); 876 leveldb_slice_t b_ = fromLdbSlice(b); 877 return (*compare_)(state_, &a_, &b_); 878 } 879 880 virtual const char* Name() const { 881 return (*name_)(state_); 882 } 883 884 // No-ops since the C binding does not support key shortening methods. 885 virtual void FindShortestSeparator( 886 std::string*, const leveldb::Slice& 887 ) const { 888 // Empty 889 } 890 virtual void FindShortSuccessor(std::string* key) const { 891 // Empty 892 } 893 }; 894 895 leveldb_comparator_t* leveldb_comparator_create( 896 void* state, 897 void (*destructor)(void* state), 898 int32_t (*compare)( 899 void* state, 900 const leveldb_slice_t* a, 901 const leveldb_slice_t* b 902 ), 903 const char* (*name)(void*) 904 ) { 905 if(destructor == NULL || compare == NULL || name == NULL) { 906 return NULL; 907 } 908 leveldb_comparator_t* result = new leveldb_comparator_t; 909 result->state_ = state; 910 result->destructor_ = destructor; 911 result->compare_ = compare; 912 result->name_ = name; 913 return result; 914 } 915 916 void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { 917 if(cmp != NULL) { 918 delete cmp; 919 } 920 } 921 922 int32_t leveldb_comparator_compare( 923 leveldb_comparator_t* cmp, 924 const leveldb_slice_t* a, 925 const leveldb_slice_t* b 926 ) { 927 if(cmp != NULL) { 928 return (*cmp->compare_)(cmp->state_, a, b); 929 } else { 930 return int32_t(0); 931 } 932 } 933 934 const char* leveldb_comparator_name( 935 leveldb_comparator_t* cmp 936 ) { 937 if(cmp != NULL) { 938 return (*cmp->name_)(cmp->state_); 939 } else { 940 return NULL; 941 } 942 } 943 944 // ---------------------------------------------------------------------------- 945 // FilterPolicy 946 // ---------------------------------------------------------------------------- 947 948 struct leveldb_filterpolicy_t : public leveldb::FilterPolicy { 949 void* state_; 950 void (*destructor_)(void* state); 951 const char* (*name_)(void* state); 952 leveldb_value_t* (*create_)( 953 void* state, 954 const leveldb_slice_t** keys, 955 int32_t num_keys 956 ); 957 leveldb_bool_t (*key_match_)( 958 void* state, 959 const leveldb_slice_t* key, 960 const leveldb_slice_t* filter 961 ); 962 963 virtual ~leveldb_filterpolicy_t() { 964 (*destructor_)(state_); 965 } 966 967 virtual void CreateFilter( 968 const leveldb::Slice* keys, int32_t n, std::string* dst 969 ) const { 970 std::vector<leveldb_slice_t*> keys_(n); 971 std::vector<leveldb_slice_t> keys_tmp_(n); 972 for(int32_t i = 0; i < n; ++i) { 973 keys_tmp_[i] = fromLdbSlice(keys[i]); 974 keys_[i] = &keys_tmp_[i]; 975 } 976 leveldb_value_t* filter = (*create_)( 977 state_, (const leveldb_slice_t**)(&keys_[0]), int32_t(n) 978 ); 979 dst->append(leveldb_value_data(filter), leveldb_value_size(filter)); 980 leveldb_value_destroy(filter); 981 } 982 983 virtual bool KeyMayMatch( 984 const leveldb::Slice& key, const leveldb::Slice& filter 985 ) const { 986 leveldb_slice_t a = fromLdbSlice(key); 987 leveldb_slice_t b = fromLdbSlice(filter); 988 leveldb_bool_t rv = (*key_match_)(state_, &a, &b); 989 return toStdBool(rv); 990 } 991 992 virtual const char* Name() const { 993 return (*name_)(state_); 994 } 995 }; 996 997 leveldb_filterpolicy_t* leveldb_filterpolicy_create( 998 void* state, 999 void (*destructor)(void* state), 1000 leveldb_value_t* (*create_filter)( 1001 void* state, 1002 const leveldb_slice_t** keys, 1003 int32_t num_keys 1004 ), 1005 leveldb_bool_t (*key_may_match)( 1006 void* state, 1007 const leveldb_slice_t* key, 1008 const leveldb_slice_t* filter 1009 ), 1010 const char* (*name)(void* state) 1011 ) { 1012 if(destructor == NULL || create_filter == NULL || key_may_match == NULL || name == NULL) { 1013 return NULL; 1014 } 1015 leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t; 1016 result->state_ = state; 1017 result->destructor_ = destructor; 1018 result->create_ = create_filter; 1019 result->key_match_ = key_may_match; 1020 result->name_ = name; 1021 return result; 1022 } 1023 1024 leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int32_t bits_per_key) { 1025 // Make a leveldb_filterpolicy_t, but override all of its methods so 1026 // they delegate to a NewBloomFilterPolicy() instead of user 1027 // supplied C functions. 1028 struct Wrapper : public leveldb_filterpolicy_t { 1029 const FilterPolicy* rep_; 1030 ~Wrapper() { delete rep_; } 1031 const char* Name() const { return rep_->Name(); } 1032 void CreateFilter( 1033 const leveldb::Slice* keys, int32_t n, std::string* dst 1034 ) const { 1035 return rep_->CreateFilter(keys, n, dst); 1036 } 1037 bool KeyMayMatch( 1038 const leveldb::Slice& key, const leveldb::Slice& filter 1039 ) const { 1040 return rep_->KeyMayMatch(key, filter); 1041 } 1042 static void DoNothing(void*) { } 1043 }; 1044 Wrapper* wrapper = new Wrapper; 1045 wrapper->state_ = NULL; 1046 wrapper->destructor_ = &Wrapper::DoNothing; 1047 wrapper->rep_ = leveldb::NewBloomFilterPolicy(bits_per_key>0? bits_per_key: 10); 1048 return wrapper; 1049 } 1050 1051 void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filterpolicy) { 1052 if(filterpolicy != NULL) { 1053 delete filterpolicy; 1054 } 1055 } 1056 1057 leveldb_value_t* leveldb_filterpolicy_create_filter( 1058 leveldb_filterpolicy_t* filterpolicy, 1059 const leveldb_slice_t** keys, 1060 int32_t num_keys 1061 ) { 1062 if(filterpolicy == NULL || keys == NULL || num_keys <= 0) { 1063 return NULL; 1064 } 1065 std::vector<leveldb::Slice> keys_; 1066 keys_.resize(size_t(num_keys)); 1067 for(int32_t i = 0; i < num_keys; ++i) { 1068 const leveldb_slice_t* pKey = *(keys+int32_t(i)); 1069 keys_[i] = leveldb::Slice(pKey->data, pKey->size); 1070 } 1071 std::string tmp; 1072 filterpolicy->CreateFilter(&keys_[0], int32_t(num_keys), &tmp); 1073 return leveldb_value_create(tmp.data(), int32_t(tmp.size())); 1074 } 1075 leveldb_bool_t leveldb_filterpolicy_key_may_match( 1076 leveldb_filterpolicy_t* filterpolicy, 1077 const leveldb_slice_t* key, 1078 const leveldb_slice_t* filter 1079 ) { 1080 if(filterpolicy == NULL || key == NULL || filter == NULL) { 1081 return fromStdBool(false); 1082 } 1083 bool rv = filterpolicy->KeyMayMatch( 1084 leveldb::Slice(key->data, key->size), 1085 leveldb::Slice(filter->data, filter->size) 1086 ); 1087 return fromStdBool(rv); 1088 } 1089 const char* leveldb_filterpolicy_name( 1090 leveldb_filterpolicy_t* filterpolicy 1091 ) { 1092 if(filterpolicy != NULL) { 1093 return filterpolicy->Name(); 1094 } else { 1095 return NULL; 1096 } 1097 } 1098 1099 // ---------------------------------------------------------------------------- 1100 // Cache 1101 // ---------------------------------------------------------------------------- 1102 1103 struct leveldb_cache_t: leveldb::Cache { 1104 DISABLE_NEW_AND_DELETE(leveldb_cache_t); 1105 }; 1106 1107 leveldb_cache_t* leveldb_cache_create_lru(int64_t capacity) { 1108 return (leveldb_cache_t*)(leveldb::NewLRUCache( 1109 size_t(capacity>0? capacity: (8<<20)) 1110 )); 1111 } 1112 1113 void leveldb_cache_destroy(leveldb_cache_t* cache) { 1114 if(cache != NULL) { 1115 delete (leveldb::Cache*)cache; 1116 } 1117 } 1118 1119 void leveldb_cache_insert( 1120 leveldb_cache_t* cache, 1121 const leveldb_slice_t* key, 1122 const leveldb_slice_t* val 1123 ) { 1124 if(cache == NULL || key == NULL || val == NULL) { 1125 return; 1126 } 1127 struct H { 1128 static void deleter(const leveldb::Slice& key, void* value) { 1129 leveldb_value_destroy((leveldb_value_t*)value); 1130 } 1131 }; 1132 leveldb::Cache::Handle* h = cache->Insert( 1133 toLdbSlice(key), 1134 leveldb_value_create(val->data, val->size), 1135 size_t(val->size), 1136 H::deleter 1137 ); 1138 cache->Release(h); 1139 } 1140 1141 leveldb_value_t* leveldb_cache_lookup( 1142 leveldb_cache_t* cache, 1143 const leveldb_slice_t* key 1144 ) { 1145 if(cache == NULL || key == NULL) { 1146 return NULL; 1147 } 1148 leveldb::Cache::Handle* h = cache->Lookup(toLdbSlice(key)); 1149 if(h == NULL) return NULL; 1150 leveldb_value_t* v = leveldb_value_create_copy((leveldb_value_t*)cache->Value(h)); 1151 cache->Release(h); 1152 return v; 1153 } 1154 1155 void leveldb_cache_erase( 1156 leveldb_cache_t* cache, 1157 const leveldb_slice_t* key 1158 ) { 1159 if(cache == NULL || key == NULL) { 1160 return; 1161 } 1162 cache->Erase(toLdbSlice(key)); 1163 } 1164 1165 // ---------------------------------------------------------------------------- 1166 // END 1167 // ---------------------------------------------------------------------------- 1168 1169