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