git » nmdb » master » tree

[master] / nmdb / be-leveldb.c

#if BE_ENABLE_LEVELDB

#include <leveldb/c.h>	/* LevelDB C API */
#include <string.h>	/* memcpy() */
#include <stdlib.h>

#include "be.h"


int xleveldb_set(struct db_conn *db, const unsigned char *key, size_t ksize,
		unsigned char *val, size_t vsize);
int xleveldb_get(struct db_conn *db, const unsigned char *key, size_t ksize,
		unsigned char *val, size_t *vsize);
int xleveldb_del(struct db_conn *db, const unsigned char *key, size_t ksize);
int xleveldb_close(struct db_conn *db);
int xleveldb_firstkey(struct db_conn *db, unsigned char *key, size_t *ksize);
int xleveldb_nextkey(struct db_conn *db,
		const unsigned char *key, size_t ksize,
		unsigned char *nextkey, size_t *nksize);

struct db_conn *xleveldb_open(const char *name, int flags)
{
	struct db_conn *db;
	leveldb_options_t *options;
	leveldb_t *level_db;

	options = leveldb_options_create();
	if (options == NULL)
		return NULL;

	leveldb_options_set_create_if_missing(options, 1);

	level_db = leveldb_open(options, name, NULL);

	leveldb_options_destroy(options);

	if (level_db == NULL)
		return NULL;

	db = malloc(sizeof(struct db_conn));
	if (db == NULL) {
		leveldb_close(level_db);
		return NULL;
	}

	db->conn = level_db;
	db->set = xleveldb_set;
	db->get = xleveldb_get;
	db->del = xleveldb_del;
	db->firstkey = xleveldb_firstkey;
	db->nextkey = xleveldb_nextkey;
	db->close = xleveldb_close;

	return db;
}


int xleveldb_close(struct db_conn *db)
{
	leveldb_close(db->conn);
	free(db);
	return 1;
}


int xleveldb_set(struct db_conn *db, const unsigned char *key, size_t ksize,
		unsigned char *val, size_t vsize)
{
	leveldb_writeoptions_t *options = leveldb_writeoptions_create();
	char *err, *origerr;

	err = origerr = malloc(1);
	leveldb_put(db->conn, options,
			(const char *) key, ksize,
			(const char *) val, vsize, &err);
	free(err);

	leveldb_writeoptions_destroy(options);

	return err == origerr;
}


int xleveldb_get(struct db_conn *db, const unsigned char *key, size_t ksize,
		unsigned char *val, size_t *vsize)
{
	int rv;
	char *db_val = NULL;
	size_t db_vsize;
	leveldb_readoptions_t *options = leveldb_readoptions_create();
	char *err, *origerr;

	err = origerr = malloc(1);
	db_val = leveldb_get(db->conn, options,
			(const char *) key, ksize, &db_vsize, &err);

	free(err);
	leveldb_readoptions_destroy(options);

	if (err != origerr || db_val == NULL || db_vsize > *vsize) {
		rv = 0;
		goto exit;
	}

	*vsize = db_vsize;
	memcpy(val, db_val, db_vsize);
	rv = 1;

exit:
	free(db_val);
	return rv;
}


int xleveldb_del(struct db_conn *db, const unsigned char *key, size_t ksize)
{
	leveldb_writeoptions_t *options = leveldb_writeoptions_create();
	char *err, *origerr;

	err = origerr = malloc(1);
	leveldb_delete(db->conn, options,
			(const char *) key, ksize, &err);
	free(err);

	leveldb_writeoptions_destroy(options);

	return err == origerr;
}


int xleveldb_firstkey(struct db_conn *db, unsigned char *key, size_t *ksize)
{
	int rv = 0;
	const char *db_key;
	size_t db_ksize;

	leveldb_readoptions_t *options = leveldb_readoptions_create();
	leveldb_iterator_t *it = leveldb_create_iterator(db->conn, options);

	leveldb_iter_seek_to_first(it);
	if (! leveldb_iter_valid(it)) {
		rv = 0;
		goto exit;
	}

	db_key = leveldb_iter_key(it, &db_ksize);

	if (db_key == NULL || db_ksize > *ksize) {
		rv = 0;
		goto exit;
	}

	*ksize = db_ksize;
	memcpy(key, db_key, db_ksize);
	rv = 1;

exit:
	leveldb_readoptions_destroy(options);
	leveldb_iter_destroy(it);
	return rv;
}


int xleveldb_nextkey(struct db_conn *db,
		const unsigned char *key, size_t ksize,
		unsigned char *nextkey, size_t *nksize)
{
	int rv;
	const char *db_nextkey;
	size_t db_nksize = 0;

	leveldb_readoptions_t *options = leveldb_readoptions_create();
	leveldb_iterator_t *it = leveldb_create_iterator(db->conn, options);

	leveldb_iter_seek(it, (const char *) key, ksize);
	if (! leveldb_iter_valid(it)) {
		rv = 0;
		goto exit;
	}

	leveldb_iter_next(it);
	if (! leveldb_iter_valid(it)) {
		rv = 0;
		goto exit;
	}

	db_nextkey = leveldb_iter_key(it, &db_nksize);

	if (db_nextkey == NULL || db_nksize > *nksize) {
		rv = 0;
		goto exit;
	}

	*nksize = db_nksize;
	memcpy(nextkey, db_nextkey, db_nksize);
	rv = 1;

exit:
	leveldb_iter_destroy(it);
	leveldb_readoptions_destroy(options);
	return rv;
}

#else

#include <stddef.h>	/* NULL */

struct db_conn *leveldb_open(const char *name, int flags)
{
	return NULL;
}

#endif