From 37b42e21eaaa0deeaf297029ef41a656d7ea35df Mon Sep 17 00:00:00 2001 From: "Bradley C. Kuszmaul" Date: Tue, 18 Dec 2007 16:22:21 +0000 Subject: [PATCH] Make db_create work under c++. Addresses #197. git-svn-id: file:///svn/tokudb@1194 c7de825b-a66e-492c-adef-691d508d4ae1 --- buildheader/db.h_4_4 | 1 + buildheader/make_db_h.c | 1 + cxx/Makefile | 3 +- cxx/db.cpp | 38 +++++++++++++++++++++++-- cxx/db_cxx.h | 49 +++++++++++++++++++++++++++----- cxx/dbt.cpp | 7 +++++ cxx/tests/Makefile | 14 ++++++++++ cxx/tests/db_create.cpp | 62 +++++++++++++++++++++++++++++++++++++++++ include/db.h | 1 + 9 files changed, 165 insertions(+), 11 deletions(-) create mode 100644 cxx/tests/Makefile create mode 100644 cxx/tests/db_create.cpp diff --git a/buildheader/db.h_4_4 b/buildheader/db.h_4_4 index c683f0d5df2..754b30f2087 100644 --- a/buildheader/db.h_4_4 +++ b/buildheader/db.h_4_4 @@ -43,6 +43,7 @@ typedef enum { #define DB_ARCH_ABS 1 #define DB_ARCH_LOG 4 #define DB_CREATE 1 +#define DB_CXX_NO_EXCEPTIONS 1 #define DB_EXCL 8192 #define DB_PRIVATE 1048576 #define DB_RDONLY 16 diff --git a/buildheader/make_db_h.c b/buildheader/make_db_h.c index f5b3bcb7af8..eeae16182db 100644 --- a/buildheader/make_db_h.c +++ b/buildheader/make_db_h.c @@ -44,6 +44,7 @@ void print_defines (void) { dodefine(DB_ARCH_LOG); dodefine(DB_CREATE); + dodefine(DB_CXX_NO_EXCEPTIONS); dodefine(DB_EXCL); dodefine(DB_PRIVATE); dodefine(DB_RDONLY); diff --git a/cxx/Makefile b/cxx/Makefile index 53398baa402..843ce102c6b 100644 --- a/cxx/Makefile +++ b/cxx/Makefile @@ -1,4 +1,5 @@ CPPFLAGS = -I../include CC = c++ -test1: test1.o dbt.o db.o +LDFLAGS = -lz +test1: test1.o dbt.o db.o dbenv.o ../lib/libdb.a diff --git a/cxx/db.cpp b/cxx/db.cpp index 92aa32b0645..8fef40d0f64 100644 --- a/cxx/db.cpp +++ b/cxx/db.cpp @@ -1,5 +1,26 @@ +#include +#include +#include #include "db_cxx.h" +Db::Db(DbEnv *env, u_int32_t flags) { + the_db = 0; + the_Env = env; + if (the_Env == 0) { + is_private_env = 1; + } + DB *tmp_db; + int ret = db_create(&tmp_db, the_Env->get_DB_ENV(), flags & !(DB_CXX_NO_EXCEPTIONS)); + if (ret!=0) { + assert(0); // make an error + } + the_db = tmp_db; + tmp_db->api_internal = this; + if (is_private_env) { + the_Env = new DbEnv(tmp_db->dbenv, flags & DB_CXX_NO_EXCEPTIONS); + } +} + Db::~Db() { if (!the_db) { close(0); // the user should have called close, but we do it here if not done. @@ -10,13 +31,24 @@ int Db::close (u_int32_t flags) { if (!the_db) { return EINVAL; } - the_db->toku_internal = 0; + the_db->api_internal = 0; - int ret = the_db->close(flags); + int ret = the_db->close(the_db, flags); the_db = 0; // Do we need to clean up "private environments"? - // What about cursors? They should be cleaned up already. + // What about cursors? They should be cleaned up already, but who did it? return ret; } + +int Db::open(DbTxn *txn, const char *filename, const char *subname, DBTYPE typ, u_int32_t flags, int mode) { + int ret = the_db->open(the_db, txn->get_DB_TXN(), filename, subname, typ, flags, mode); + return ret; +} + +int Db::put(DbTxn *txn, Dbt *key, Dbt *data, u_int32_t flags) { + int ret = the_db->put(the_db, txn->get_DB_TXN(), key->get_DBT(), data->get_DBT(), flags); + return ret; +} + diff --git a/cxx/db_cxx.h b/cxx/db_cxx.h index fd9242490a5..2d99ebd258c 100644 --- a/cxx/db_cxx.h +++ b/cxx/db_cxx.h @@ -2,6 +2,9 @@ #include class Dbt; +class DbEnv; +class DbTxn; +class Dbc; // DBT and Dbt objects are the same pointers. So watch out if you use Dbt to make other classes (e.g., with subclassing). class Dbt : private DBT @@ -16,6 +19,7 @@ class Dbt : private DBT DBT *get_DBT(void) { return (DBT*)this; } + Dbt(void */*data*/, u_int32_t /*size*/); Dbt(void); ~Dbt(); @@ -29,17 +33,17 @@ class Db { Db(DbEnv *dbenv, u_int32_t flags); ~Db(); - DB *Db::get_DB(void) { + DB *get_DB(void) { return the_db; } - const DB *Db::get_const_DB() const { + const DB *get_const_DB() const { return the_db; } - static Db *Db::get_Db(DB *db) { - return (Db*)db->toku_internal; + static Db *get_Db(DB *db) { + return (Db*)db->api_internal; } - static const Db *Db::get_const_Db(const DB *db) { - return (Db*)db->toku_internal; + static const Db *get_const_Db(const DB *db) { + return (Db*)db->api_internal; } /* C++ analogues of the C functions. */ @@ -55,5 +59,36 @@ class Db { private: DB *the_db; - + DbEnv *the_Env; + int is_private_env; }; + +class DbEnv { + friend class Db; + public: + DbEnv(u_int32_t flags); + + DB_ENV *get_DB_ENV(void) { + return the_env; + } + + /* C++ analogues of the C functions. */ + int close(u_int32_t); + + private: + DB_ENV *the_env; + + DbEnv(DB_ENV *, u_int32_t flags); +}; + + +class DbTxn { + public: + DB_TXN *get_DB_TXN() + { + return the_txn; + } + private: + DB_TXN *the_txn; +}; + diff --git a/cxx/dbt.cpp b/cxx/dbt.cpp index bb7ae4a7250..0f140a10df3 100644 --- a/cxx/dbt.cpp +++ b/cxx/dbt.cpp @@ -5,6 +5,13 @@ Dbt::Dbt(void) { memset(dbt, 0, sizeof(*dbt)); } +Dbt::Dbt(void *data, u_int32_t size) { + DBT *dbt = this; + memset(dbt, 0, sizeof(*dbt)); + set_data(data); + set_size(size); +} + Dbt::~Dbt(void) { } diff --git a/cxx/tests/Makefile b/cxx/tests/Makefile new file mode 100644 index 00000000000..f8ed28923e5 --- /dev/null +++ b/cxx/tests/Makefile @@ -0,0 +1,14 @@ +SRCS = $(wildcard *.cpp) +TARGETS = $(patsubst %.cpp,%,$(SRCS)) + +DBCXX = ../dbt.o ../db.o ../dbenv.o ../dbt.o +CPPFLAGS = -I../ -I../../include +CXXFLAGS = -Wall -g +LDFLAGS = -L../lib -ldb + +$(TARGETS): $(DBCXX) + +all: $(TARGETS) + +clean: + rm -rf $(TARGETS) diff --git a/cxx/tests/db_create.cpp b/cxx/tests/db_create.cpp new file mode 100644 index 00000000000..06052695193 --- /dev/null +++ b/cxx/tests/db_create.cpp @@ -0,0 +1,62 @@ +#include +#include + +int dbcreate(char *dbfile, char *dbname, int argc, char *argv[]) { + int r; +#if USE_ENV + DbEnv *env = new DbEnv(DB_CXX_NO_EXCEPTIONS); + r = env->open(".", DB_INIT_MPOOL + DB_CREATE + DB_PRIVATE, 0777); assert(r == 0); +#else + DbEnv *env = 0; +#endif + Db *db = new Db(env, DB_CXX_NO_EXCEPTIONS); + r = db->open(0, dbfile, dbname, DB_BTREE, DB_CREATE, 0777); + assert(r == 0); + + int i = 0; + while (i < argc) { + char *k = argv[i++]; + if (i < argc) { + char *v = argv[i++]; + Dbt key(k, strlen(k)); Dbt val(v, strlen(v)); + r = db->put(0, &key, &val, 0); assert(r == 0); + } + } + + r = db->close(0); assert(r == 0); + if (env) { + r = env->close(0); assert(r == 0); + delete env; + } + return 0; +} + +int usage() { + printf("db_create [-s DBNAME] DBFILE [KEY VAL]*\n"); + return 1; +} + +int main(int argc, char *argv[]) { + char *dbname = 0; + + int i; + for (i=1; i= argc) + return usage(); + dbname = argv[i]; + continue; + } + break; + } + + if (i >= argc) + return usage(); + char *dbfile = argv[i++]; + return dbcreate(dbfile, dbname, argc-i, &argv[i]); +} + diff --git a/include/db.h b/include/db.h index c683f0d5df2..754b30f2087 100644 --- a/include/db.h +++ b/include/db.h @@ -43,6 +43,7 @@ typedef enum { #define DB_ARCH_ABS 1 #define DB_ARCH_LOG 4 #define DB_CREATE 1 +#define DB_CXX_NO_EXCEPTIONS 1 #define DB_EXCL 8192 #define DB_PRIVATE 1048576 #define DB_RDONLY 16