Line data Source code
1 : // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 :
5 : #include "leveldb/c.h"
6 :
7 : #include <stdlib.h>
8 : #include <unistd.h>
9 : #include "leveldb/cache.h"
10 : #include "leveldb/comparator.h"
11 : #include "leveldb/db.h"
12 : #include "leveldb/env.h"
13 : #include "leveldb/filter_policy.h"
14 : #include "leveldb/iterator.h"
15 : #include "leveldb/options.h"
16 : #include "leveldb/status.h"
17 : #include "leveldb/write_batch.h"
18 :
19 : using leveldb::Cache;
20 : using leveldb::Comparator;
21 : using leveldb::CompressionType;
22 : using leveldb::DB;
23 : using leveldb::Env;
24 : using leveldb::FileLock;
25 : using leveldb::FilterPolicy;
26 : using leveldb::Iterator;
27 : using leveldb::kMajorVersion;
28 : using leveldb::kMinorVersion;
29 : using leveldb::Logger;
30 : using leveldb::NewBloomFilterPolicy;
31 : using leveldb::NewLRUCache;
32 : using leveldb::Options;
33 : using leveldb::RandomAccessFile;
34 : using leveldb::Range;
35 : using leveldb::ReadOptions;
36 : using leveldb::SequentialFile;
37 : using leveldb::Slice;
38 : using leveldb::Snapshot;
39 : using leveldb::Status;
40 : using leveldb::WritableFile;
41 : using leveldb::WriteBatch;
42 : using leveldb::WriteOptions;
43 :
44 : extern "C" {
45 :
46 : struct leveldb_t { DB* rep; };
47 : struct leveldb_iterator_t { Iterator* rep; };
48 0 : struct leveldb_writebatch_t { WriteBatch rep; };
49 : struct leveldb_snapshot_t { const Snapshot* rep; };
50 0 : struct leveldb_readoptions_t { ReadOptions rep; };
51 0 : struct leveldb_writeoptions_t { WriteOptions rep; };
52 0 : struct leveldb_options_t { Options rep; };
53 : struct leveldb_cache_t { Cache* rep; };
54 : struct leveldb_seqfile_t { SequentialFile* rep; };
55 : struct leveldb_randomfile_t { RandomAccessFile* rep; };
56 : struct leveldb_writablefile_t { WritableFile* rep; };
57 : struct leveldb_logger_t { Logger* rep; };
58 : struct leveldb_filelock_t { FileLock* rep; };
59 :
60 0 : struct leveldb_comparator_t : public Comparator {
61 : void* state_;
62 : void (*destructor_)(void*);
63 : int (*compare_)(
64 : void*,
65 : const char* a, size_t alen,
66 : const char* b, size_t blen);
67 : const char* (*name_)(void*);
68 :
69 0 : virtual ~leveldb_comparator_t() {
70 0 : (*destructor_)(state_);
71 0 : }
72 :
73 0 : virtual int Compare(const Slice& a, const Slice& b) const {
74 0 : return (*compare_)(state_, a.data(), a.size(), b.data(), b.size());
75 : }
76 :
77 0 : virtual const char* Name() const {
78 0 : return (*name_)(state_);
79 : }
80 :
81 : // No-ops since the C binding does not support key shortening methods.
82 0 : virtual void FindShortestSeparator(std::string*, const Slice&) const { }
83 0 : virtual void FindShortSuccessor(std::string* key) const { }
84 : };
85 :
86 0 : struct leveldb_filterpolicy_t : public FilterPolicy {
87 : void* state_;
88 : void (*destructor_)(void*);
89 : const char* (*name_)(void*);
90 : char* (*create_)(
91 : void*,
92 : const char* const* key_array, const size_t* key_length_array,
93 : int num_keys,
94 : size_t* filter_length);
95 : unsigned char (*key_match_)(
96 : void*,
97 : const char* key, size_t length,
98 : const char* filter, size_t filter_length);
99 :
100 0 : virtual ~leveldb_filterpolicy_t() {
101 0 : (*destructor_)(state_);
102 0 : }
103 :
104 0 : virtual const char* Name() const {
105 0 : return (*name_)(state_);
106 : }
107 :
108 0 : virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
109 0 : std::vector<const char*> key_pointers(n);
110 0 : std::vector<size_t> key_sizes(n);
111 0 : for (int i = 0; i < n; i++) {
112 0 : key_pointers[i] = keys[i].data();
113 0 : key_sizes[i] = keys[i].size();
114 : }
115 : size_t len;
116 0 : char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len);
117 0 : dst->append(filter, len);
118 0 : free(filter);
119 0 : }
120 :
121 0 : virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
122 : return (*key_match_)(state_, key.data(), key.size(),
123 0 : filter.data(), filter.size());
124 : }
125 : };
126 :
127 : struct leveldb_env_t {
128 : Env* rep;
129 : bool is_default;
130 : };
131 :
132 0 : static bool SaveError(char** errptr, const Status& s) {
133 0 : assert(errptr != NULL);
134 0 : if (s.ok()) {
135 : return false;
136 0 : } else if (*errptr == NULL) {
137 0 : *errptr = strdup(s.ToString().c_str());
138 : } else {
139 : // TODO(sanjay): Merge with existing error?
140 0 : free(*errptr);
141 0 : *errptr = strdup(s.ToString().c_str());
142 : }
143 : return true;
144 : }
145 :
146 0 : static char* CopyString(const std::string& str) {
147 0 : char* result = reinterpret_cast<char*>(malloc(sizeof(char) * str.size()));
148 0 : memcpy(result, str.data(), sizeof(char) * str.size());
149 0 : return result;
150 : }
151 :
152 0 : leveldb_t* leveldb_open(
153 : const leveldb_options_t* options,
154 : const char* name,
155 : char** errptr) {
156 : DB* db;
157 0 : if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) {
158 : return NULL;
159 : }
160 0 : leveldb_t* result = new leveldb_t;
161 0 : result->rep = db;
162 0 : return result;
163 : }
164 :
165 0 : void leveldb_close(leveldb_t* db) {
166 0 : delete db->rep;
167 0 : delete db;
168 0 : }
169 :
170 0 : void leveldb_put(
171 : leveldb_t* db,
172 : const leveldb_writeoptions_t* options,
173 : const char* key, size_t keylen,
174 : const char* val, size_t vallen,
175 : char** errptr) {
176 : SaveError(errptr,
177 0 : db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen)));
178 0 : }
179 :
180 0 : void leveldb_delete(
181 : leveldb_t* db,
182 : const leveldb_writeoptions_t* options,
183 : const char* key, size_t keylen,
184 : char** errptr) {
185 0 : SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen)));
186 0 : }
187 :
188 :
189 0 : void leveldb_write(
190 : leveldb_t* db,
191 : const leveldb_writeoptions_t* options,
192 : leveldb_writebatch_t* batch,
193 : char** errptr) {
194 0 : SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
195 0 : }
196 :
197 0 : char* leveldb_get(
198 : leveldb_t* db,
199 : const leveldb_readoptions_t* options,
200 : const char* key, size_t keylen,
201 : size_t* vallen,
202 : char** errptr) {
203 0 : char* result = NULL;
204 : std::string tmp;
205 0 : Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp);
206 0 : if (s.ok()) {
207 0 : *vallen = tmp.size();
208 0 : result = CopyString(tmp);
209 : } else {
210 0 : *vallen = 0;
211 0 : if (!s.IsNotFound()) {
212 0 : SaveError(errptr, s);
213 : }
214 : }
215 0 : return result;
216 : }
217 :
218 0 : leveldb_iterator_t* leveldb_create_iterator(
219 : leveldb_t* db,
220 : const leveldb_readoptions_t* options) {
221 0 : leveldb_iterator_t* result = new leveldb_iterator_t;
222 0 : result->rep = db->rep->NewIterator(options->rep);
223 0 : return result;
224 : }
225 :
226 0 : const leveldb_snapshot_t* leveldb_create_snapshot(
227 : leveldb_t* db) {
228 0 : leveldb_snapshot_t* result = new leveldb_snapshot_t;
229 0 : result->rep = db->rep->GetSnapshot();
230 0 : return result;
231 : }
232 :
233 0 : void leveldb_release_snapshot(
234 : leveldb_t* db,
235 : const leveldb_snapshot_t* snapshot) {
236 0 : db->rep->ReleaseSnapshot(snapshot->rep);
237 0 : delete snapshot;
238 0 : }
239 :
240 0 : char* leveldb_property_value(
241 : leveldb_t* db,
242 : const char* propname) {
243 : std::string tmp;
244 0 : if (db->rep->GetProperty(Slice(propname), &tmp)) {
245 : // We use strdup() since we expect human readable output.
246 0 : return strdup(tmp.c_str());
247 : } else {
248 : return NULL;
249 : }
250 : }
251 :
252 0 : void leveldb_approximate_sizes(
253 : leveldb_t* db,
254 : int num_ranges,
255 : const char* const* range_start_key, const size_t* range_start_key_len,
256 : const char* const* range_limit_key, const size_t* range_limit_key_len,
257 : uint64_t* sizes) {
258 0 : Range* ranges = new Range[num_ranges];
259 0 : for (int i = 0; i < num_ranges; i++) {
260 0 : ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]);
261 0 : ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]);
262 : }
263 0 : db->rep->GetApproximateSizes(ranges, num_ranges, sizes);
264 0 : delete[] ranges;
265 0 : }
266 :
267 0 : void leveldb_compact_range(
268 : leveldb_t* db,
269 : const char* start_key, size_t start_key_len,
270 : const char* limit_key, size_t limit_key_len) {
271 : Slice a, b;
272 : db->rep->CompactRange(
273 : // Pass NULL Slice if corresponding "const char*" is NULL
274 : (start_key ? (a = Slice(start_key, start_key_len), &a) : NULL),
275 0 : (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : NULL));
276 0 : }
277 :
278 0 : void leveldb_destroy_db(
279 : const leveldb_options_t* options,
280 : const char* name,
281 : char** errptr) {
282 0 : SaveError(errptr, DestroyDB(name, options->rep));
283 0 : }
284 :
285 0 : void leveldb_repair_db(
286 : const leveldb_options_t* options,
287 : const char* name,
288 : char** errptr) {
289 0 : SaveError(errptr, RepairDB(name, options->rep));
290 0 : }
291 :
292 0 : void leveldb_iter_destroy(leveldb_iterator_t* iter) {
293 0 : delete iter->rep;
294 0 : delete iter;
295 0 : }
296 :
297 0 : unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) {
298 0 : return iter->rep->Valid();
299 : }
300 :
301 0 : void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) {
302 0 : iter->rep->SeekToFirst();
303 0 : }
304 :
305 0 : void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) {
306 0 : iter->rep->SeekToLast();
307 0 : }
308 :
309 0 : void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) {
310 0 : iter->rep->Seek(Slice(k, klen));
311 0 : }
312 :
313 0 : void leveldb_iter_next(leveldb_iterator_t* iter) {
314 0 : iter->rep->Next();
315 0 : }
316 :
317 0 : void leveldb_iter_prev(leveldb_iterator_t* iter) {
318 0 : iter->rep->Prev();
319 0 : }
320 :
321 0 : const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) {
322 0 : Slice s = iter->rep->key();
323 0 : *klen = s.size();
324 0 : return s.data();
325 : }
326 :
327 0 : const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) {
328 0 : Slice s = iter->rep->value();
329 0 : *vlen = s.size();
330 0 : return s.data();
331 : }
332 :
333 0 : void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) {
334 0 : SaveError(errptr, iter->rep->status());
335 0 : }
336 :
337 0 : leveldb_writebatch_t* leveldb_writebatch_create() {
338 0 : return new leveldb_writebatch_t;
339 : }
340 :
341 0 : void leveldb_writebatch_destroy(leveldb_writebatch_t* b) {
342 0 : delete b;
343 0 : }
344 :
345 0 : void leveldb_writebatch_clear(leveldb_writebatch_t* b) {
346 0 : b->rep.Clear();
347 0 : }
348 :
349 0 : void leveldb_writebatch_put(
350 : leveldb_writebatch_t* b,
351 : const char* key, size_t klen,
352 : const char* val, size_t vlen) {
353 0 : b->rep.Put(Slice(key, klen), Slice(val, vlen));
354 0 : }
355 :
356 0 : void leveldb_writebatch_delete(
357 : leveldb_writebatch_t* b,
358 : const char* key, size_t klen) {
359 0 : b->rep.Delete(Slice(key, klen));
360 0 : }
361 :
362 0 : void leveldb_writebatch_iterate(
363 : leveldb_writebatch_t* b,
364 : void* state,
365 : void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
366 : void (*deleted)(void*, const char* k, size_t klen)) {
367 0 : class H : public WriteBatch::Handler {
368 : public:
369 : void* state_;
370 : void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
371 : void (*deleted_)(void*, const char* k, size_t klen);
372 0 : virtual void Put(const Slice& key, const Slice& value) {
373 0 : (*put_)(state_, key.data(), key.size(), value.data(), value.size());
374 0 : }
375 0 : virtual void Delete(const Slice& key) {
376 0 : (*deleted_)(state_, key.data(), key.size());
377 0 : }
378 : };
379 : H handler;
380 0 : handler.state_ = state;
381 0 : handler.put_ = put;
382 0 : handler.deleted_ = deleted;
383 0 : b->rep.Iterate(&handler);
384 0 : }
385 :
386 0 : leveldb_options_t* leveldb_options_create() {
387 0 : return new leveldb_options_t;
388 : }
389 :
390 0 : void leveldb_options_destroy(leveldb_options_t* options) {
391 0 : delete options;
392 0 : }
393 :
394 0 : void leveldb_options_set_comparator(
395 : leveldb_options_t* opt,
396 : leveldb_comparator_t* cmp) {
397 0 : opt->rep.comparator = cmp;
398 0 : }
399 :
400 0 : void leveldb_options_set_filter_policy(
401 : leveldb_options_t* opt,
402 : leveldb_filterpolicy_t* policy) {
403 0 : opt->rep.filter_policy = policy;
404 0 : }
405 :
406 0 : void leveldb_options_set_create_if_missing(
407 : leveldb_options_t* opt, unsigned char v) {
408 0 : opt->rep.create_if_missing = v;
409 0 : }
410 :
411 0 : void leveldb_options_set_error_if_exists(
412 : leveldb_options_t* opt, unsigned char v) {
413 0 : opt->rep.error_if_exists = v;
414 0 : }
415 :
416 0 : void leveldb_options_set_paranoid_checks(
417 : leveldb_options_t* opt, unsigned char v) {
418 0 : opt->rep.paranoid_checks = v;
419 0 : }
420 :
421 0 : void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) {
422 0 : opt->rep.env = (env ? env->rep : NULL);
423 0 : }
424 :
425 0 : void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) {
426 0 : opt->rep.info_log = (l ? l->rep : NULL);
427 0 : }
428 :
429 0 : void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) {
430 0 : opt->rep.write_buffer_size = s;
431 0 : }
432 :
433 0 : void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) {
434 0 : opt->rep.max_open_files = n;
435 0 : }
436 :
437 0 : void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) {
438 0 : opt->rep.block_cache = c->rep;
439 0 : }
440 :
441 0 : void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) {
442 0 : opt->rep.block_size = s;
443 0 : }
444 :
445 0 : void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) {
446 0 : opt->rep.block_restart_interval = n;
447 0 : }
448 :
449 0 : void leveldb_options_set_compression(leveldb_options_t* opt, int t) {
450 0 : opt->rep.compression = static_cast<CompressionType>(t);
451 0 : }
452 :
453 0 : leveldb_comparator_t* leveldb_comparator_create(
454 : void* state,
455 : void (*destructor)(void*),
456 : int (*compare)(
457 : void*,
458 : const char* a, size_t alen,
459 : const char* b, size_t blen),
460 : const char* (*name)(void*)) {
461 0 : leveldb_comparator_t* result = new leveldb_comparator_t;
462 0 : result->state_ = state;
463 0 : result->destructor_ = destructor;
464 0 : result->compare_ = compare;
465 0 : result->name_ = name;
466 0 : return result;
467 : }
468 :
469 0 : void leveldb_comparator_destroy(leveldb_comparator_t* cmp) {
470 0 : delete cmp;
471 0 : }
472 :
473 0 : leveldb_filterpolicy_t* leveldb_filterpolicy_create(
474 : void* state,
475 : void (*destructor)(void*),
476 : char* (*create_filter)(
477 : void*,
478 : const char* const* key_array, const size_t* key_length_array,
479 : int num_keys,
480 : size_t* filter_length),
481 : unsigned char (*key_may_match)(
482 : void*,
483 : const char* key, size_t length,
484 : const char* filter, size_t filter_length),
485 : const char* (*name)(void*)) {
486 0 : leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t;
487 0 : result->state_ = state;
488 0 : result->destructor_ = destructor;
489 0 : result->create_ = create_filter;
490 0 : result->key_match_ = key_may_match;
491 0 : result->name_ = name;
492 0 : return result;
493 : }
494 :
495 0 : void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) {
496 0 : delete filter;
497 0 : }
498 :
499 0 : leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) {
500 : // Make a leveldb_filterpolicy_t, but override all of its methods so
501 : // they delegate to a NewBloomFilterPolicy() instead of user
502 : // supplied C functions.
503 0 : struct Wrapper : public leveldb_filterpolicy_t {
504 : const FilterPolicy* rep_;
505 0 : ~Wrapper() { delete rep_; }
506 0 : const char* Name() const { return rep_->Name(); }
507 0 : void CreateFilter(const Slice* keys, int n, std::string* dst) const {
508 0 : return rep_->CreateFilter(keys, n, dst);
509 : }
510 0 : bool KeyMayMatch(const Slice& key, const Slice& filter) const {
511 0 : return rep_->KeyMayMatch(key, filter);
512 : }
513 0 : static void DoNothing(void*) { }
514 : };
515 0 : Wrapper* wrapper = new Wrapper;
516 0 : wrapper->rep_ = NewBloomFilterPolicy(bits_per_key);
517 0 : wrapper->state_ = NULL;
518 0 : wrapper->destructor_ = &Wrapper::DoNothing;
519 0 : return wrapper;
520 : }
521 :
522 0 : leveldb_readoptions_t* leveldb_readoptions_create() {
523 0 : return new leveldb_readoptions_t;
524 : }
525 :
526 0 : void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) {
527 0 : delete opt;
528 0 : }
529 :
530 0 : void leveldb_readoptions_set_verify_checksums(
531 : leveldb_readoptions_t* opt,
532 : unsigned char v) {
533 0 : opt->rep.verify_checksums = v;
534 0 : }
535 :
536 0 : void leveldb_readoptions_set_fill_cache(
537 : leveldb_readoptions_t* opt, unsigned char v) {
538 0 : opt->rep.fill_cache = v;
539 0 : }
540 :
541 0 : void leveldb_readoptions_set_snapshot(
542 : leveldb_readoptions_t* opt,
543 : const leveldb_snapshot_t* snap) {
544 0 : opt->rep.snapshot = (snap ? snap->rep : NULL);
545 0 : }
546 :
547 0 : leveldb_writeoptions_t* leveldb_writeoptions_create() {
548 0 : return new leveldb_writeoptions_t;
549 : }
550 :
551 0 : void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) {
552 0 : delete opt;
553 0 : }
554 :
555 0 : void leveldb_writeoptions_set_sync(
556 : leveldb_writeoptions_t* opt, unsigned char v) {
557 0 : opt->rep.sync = v;
558 0 : }
559 :
560 0 : leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) {
561 0 : leveldb_cache_t* c = new leveldb_cache_t;
562 0 : c->rep = NewLRUCache(capacity);
563 0 : return c;
564 : }
565 :
566 0 : void leveldb_cache_destroy(leveldb_cache_t* cache) {
567 0 : delete cache->rep;
568 0 : delete cache;
569 0 : }
570 :
571 0 : leveldb_env_t* leveldb_create_default_env() {
572 0 : leveldb_env_t* result = new leveldb_env_t;
573 0 : result->rep = Env::Default();
574 0 : result->is_default = true;
575 0 : return result;
576 : }
577 :
578 0 : void leveldb_env_destroy(leveldb_env_t* env) {
579 0 : if (!env->is_default) delete env->rep;
580 0 : delete env;
581 0 : }
582 :
583 0 : void leveldb_free(void* ptr) {
584 0 : free(ptr);
585 0 : }
586 :
587 0 : int leveldb_major_version() {
588 0 : return kMajorVersion;
589 : }
590 :
591 0 : int leveldb_minor_version() {
592 0 : return kMinorVersion;
593 : }
594 :
595 : } // end extern "C"
|