hamsterdb Embedded Database  2.1.1
hamsterdb.hpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005-2013 Christoph Rupp (chris@crupp.de).
00003  *
00004  * This program is free software; you can redistribute it and/or modify it
00005  * under the terms of the GNU General Public License as published by the
00006  * Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * See files COPYING.* for License information.
00010  */
00011 
00026 #ifndef HAM_HAMSTERDB_HPP__
00027 #define HAM_HAMSTERDB_HPP__
00028 
00029 #include <ham/hamsterdb.h>
00030 #include <ham/hamsterdb_int.h>
00031 #include <cstring>
00032 #include <vector>
00033 
00034 #if defined(_MSC_VER) && defined(_DEBUG) && !defined(_CRTDBG_MAP_ALLOC)
00035 #  define _CRTDBG_MAP_ALLOC
00036 #  include <crtdbg.h>
00037 #endif
00038 
00047 namespace hamsterdb {
00048 
00049 class txn;
00050 class db;
00051 class env;
00052 
00058 class error {
00059   public:
00061     error(ham_status_t st)
00062       : m_errno(st) {
00063     };
00064 
00066     ham_status_t get_errno() const {
00067         return (m_errno);
00068     }
00069 
00071     const char *get_string() const {
00072         return (ham_strerror(m_errno));
00073     }
00074 
00075 private:
00076     ham_status_t m_errno;
00077 };
00078 
00084 class key {
00085   public:
00087     key(void *data = 0, ham_u16_t size = 0, ham_u32_t flags = 0) {
00088       memset(&m_key, 0, sizeof(m_key));
00089       m_key.data = data;
00090       m_key.size = size;
00091       m_key.flags = flags;
00092       if (m_key.size != size) // check for overflow
00093         throw error(HAM_INV_KEYSIZE);
00094     }
00095 
00097     key(const key &other)
00098       : m_key(other.m_key) {
00099     }
00100 
00102     key &operator=(const key &other) {
00103       if (&other != this)
00104         m_key = other.m_key;
00105       return (*this);
00106     }
00107 
00109     void *get_data() const {
00110       return (m_key.data);
00111     }
00112 
00114     void set_data(void *data) {
00115       m_key.data = data;
00116     }
00117 
00119     ham_u16_t get_size() const {
00120       return (m_key.size);
00121     }
00122 
00124     void set_size(ham_u16_t size) {
00125       m_key.size = size;
00126     }
00127 
00129     template <class T>
00130     void set(T &t) {
00131       set_data(&t);
00132       set_size(sizeof(t));
00133     }
00134 
00136     ham_u32_t get_flags() const {
00137       return (m_key.flags);
00138     }
00139 
00141     void set_flags(ham_u32_t flags) {
00142       m_key.flags = flags;
00143     }
00144 
00146     ham_key_t *get_handle() {
00147       return (&m_key);
00148     }
00149 
00151     int get_approximate_match_type() {
00152       return (ham_key_get_approximate_match_type(&m_key));
00153     }
00154 
00155 private:
00156     ham_key_t m_key;
00157 };
00158 
00164 class record {
00165   public:
00167     record(void *data = 0, ham_u32_t size = 0, ham_u32_t flags = 0) {
00168       memset(&m_rec, 0, sizeof(m_rec));
00169       m_rec.data = data;
00170       m_rec.size = size;
00171       m_rec.flags = flags;
00172     }
00173 
00175     record(const record &other)
00176       : m_rec(other.m_rec) {
00177     }
00178 
00180     record &operator=(const record &other) {
00181       m_rec = other.m_rec;
00182       return (*this);
00183     }
00184 
00186     void *get_data() const {
00187       return (m_rec.data);
00188     }
00189 
00191     void set_data(void *data) {
00192       m_rec.data = data;
00193     }
00194 
00196     ham_u32_t get_size() const {
00197       return (m_rec.size);
00198     }
00199 
00201     void set_size(ham_u32_t size) {
00202       m_rec.size = size;
00203     }
00204 
00206     ham_u32_t get_flags() const {
00207       return (m_rec.flags);
00208     }
00209 
00211     void set_flags(ham_u32_t flags) {
00212       m_rec.flags = flags;
00213     }
00214 
00216     ham_record_t *get_handle() {
00217       return (&m_rec);
00218     }
00219 
00220   protected:
00221     ham_record_t m_rec;
00222 };
00223 
00224 
00230 class txn {
00231   public:
00233     txn(ham_txn_t *t = 0)
00234       : m_txn(t) {
00235     }
00236 
00238     void abort() {
00239       ham_status_t st = ham_txn_abort(m_txn, 0);
00240       if (st)
00241         throw error(st);
00242     }
00243 
00245     void commit() {
00246       ham_status_t st = ham_txn_commit(m_txn, 0);
00247       if (st)
00248         throw error(st);
00249     }
00250 
00251     std::string get_name() {
00252       const char *p = ham_txn_get_name(m_txn);
00253       return (p ? p : "");
00254     }
00255 
00257     ham_txn_t *get_handle() {
00258       return (m_txn);
00259     }
00260 
00261   protected:
00262     ham_txn_t *m_txn;
00263 };
00264 
00265 
00271 class db {
00272   public:
00274     static void set_errhandler(ham_errhandler_fun f) {
00275       ham_set_errhandler(f);
00276     }
00277 
00279     static void get_version(ham_u32_t *major, ham_u32_t *minor,
00280                   ham_u32_t *revision) {
00281       ham_get_version(major, minor, revision);
00282     }
00283 
00285     static void get_license(const char **licensee, const char **product) {
00286       ham_get_license(licensee, product);
00287     }
00288 
00290     db()
00291       : m_db(0) {
00292     }
00293 
00295     ~db() {
00296       close();
00297     }
00298 
00305     db &operator=(const db &other) {
00306       db &rhs = (db &)other;
00307       if (this == &other)
00308         return (*this);
00309       close();
00310       m_db = rhs.m_db;
00311       rhs.m_db = 0;
00312       return (*this);
00313     }
00314 
00316     ham_status_t get_error() {
00317       return (ham_db_get_error(m_db));
00318     }
00319 
00321     void set_prefix_compare_func(ham_prefix_compare_func_t foo) {
00322       ham_status_t st = ham_db_set_prefix_compare_func(m_db, foo);
00323       if (st)
00324         throw error(st);
00325     }
00326 
00328     void set_compare_func(ham_compare_func_t foo) {
00329       ham_status_t st = ham_db_set_compare_func(m_db, foo);
00330       if (st)
00331         throw error(st);
00332     }
00333 
00335     record find(txn *t, key *k, ham_u32_t flags = 0) {
00336       record r;
00337       ham_status_t st = ham_db_find(m_db,
00338                 t ? t->get_handle() : 0,
00339                 k ? k->get_handle() : 0,
00340                 r.get_handle(), flags);
00341       if (st)
00342         throw error(st);
00343       return (r);
00344     }
00345 
00347     record find(key *k, ham_u32_t flags = 0) {
00348       return (find(0, k, flags));
00349     }
00350 
00352     void insert(txn *t, key *k, record *r, ham_u32_t flags = 0) {
00353       ham_status_t st = ham_db_insert(m_db,
00354                 t ? t->get_handle() : 0,
00355                 k ? k->get_handle() : 0,
00356                 r ? r->get_handle() : 0, flags);
00357       if (st)
00358         throw error(st);
00359     }
00360 
00362     void insert(key *k, record *r, ham_u32_t flags=0) {
00363       insert(0, k, r, flags);
00364     }
00365 
00367     void erase(key *k, ham_u32_t flags = 0) {
00368       erase(0, k, flags);
00369     }
00370 
00372     void erase(txn *t, key *k, ham_u32_t flags = 0) {
00373       ham_status_t st = ham_db_erase(m_db,
00374                 t ? t->get_handle() : 0,
00375                 k ? k->get_handle() : 0, flags);
00376       if (st)
00377         throw error(st);
00378     }
00379 
00381     ham_u64_t get_key_count(ham_txn_t *txn = 0, ham_u32_t flags = 0) {
00382       ham_u64_t count = 0;
00383       ham_status_t st = ham_db_get_key_count(m_db, txn, flags, &count);
00384       if (st)
00385         throw error(st);
00386       return (count);
00387     }
00388 
00390     void get_parameters(ham_parameter_t *param) {
00391       ham_status_t st = ham_db_get_parameters(m_db, param);
00392       if (st)
00393         throw error(st);
00394     }
00395 
00397     void close(ham_u32_t flags = 0) {
00398       if (!m_db)
00399         return;
00400       // disable auto-cleanup; all objects will be destroyed when 
00401       // going out of scope
00402       flags &= ~HAM_AUTO_CLEANUP;
00403       ham_status_t st = ham_db_close(m_db, flags);
00404       if (st)
00405         throw error(st);
00406       m_db = 0;
00407     }
00408 
00410     ham_db_t *get_handle() {
00411       return (m_db);
00412     }
00413 
00414 protected:
00415     friend class env;
00416 
00417     /* Copy Constructor. Is protected and should not be used. */
00418     db(ham_db_t *db)
00419       : m_db(db) {
00420     }
00421 
00422   private:
00423     ham_db_t *m_db;
00424 };
00425 
00426 
00432 class cursor {
00433   public:
00435     cursor(db *db = 0, txn *t = 0, ham_u32_t flags = 0)
00436       : m_cursor(0) {
00437       create(db, t, flags);
00438     }
00439 
00441     cursor(txn *t, db *db = 0, ham_u32_t flags = 0)
00442       : m_cursor(0) {
00443       create(db, t, flags);
00444     }
00445 
00447     ~cursor() {
00448       close();
00449     }
00450 
00452     void create(db *db, txn *t = 0, ham_u32_t flags = 0) {
00453       if (m_cursor)
00454         close();
00455       if (db) {
00456         ham_status_t st = ham_cursor_create(&m_cursor, db->get_handle(),
00457                     t ? t->get_handle() : 0, flags);
00458         if (st)
00459           throw error(st);
00460       }
00461     }
00462 
00464     cursor clone() {
00465       ham_cursor_t *dest;
00466       ham_status_t st = ham_cursor_clone(m_cursor, &dest);
00467       if (st)
00468         throw error(st);
00469       return (cursor(dest));
00470     }
00471 
00473     void move(key *k, record *r, ham_u32_t flags = 0) {
00474       ham_status_t st = ham_cursor_move(m_cursor, k ? k->get_handle() : 0,
00475                         r ? r->get_handle() : 0, flags);
00476       if (st)
00477         throw error(st);
00478     }
00479 
00481     void move_first(key *k = 0, record *r = 0) {
00482       move(k, r, HAM_CURSOR_FIRST);
00483     }
00484 
00486     void move_last(key *k = 0, record *r = 0) {
00487       move(k, r, HAM_CURSOR_LAST);
00488     }
00489 
00491     void move_next(key *k = 0, record *r = 0) {
00492       move(k, r, HAM_CURSOR_NEXT);
00493     }
00494 
00496     void move_previous(key *k = 0, record *r = 0) {
00497       move(k, r, HAM_CURSOR_PREVIOUS);
00498     }
00499 
00501     void overwrite(record *r, ham_u32_t flags = 0) {
00502       ham_status_t st = ham_cursor_overwrite(m_cursor,
00503                             r ? r->get_handle() : 0, flags);
00504       if (st)
00505         throw error(st);
00506     }
00507 
00509     void find(key *k, record *r = 0, ham_u32_t flags = 0) {
00510       ham_status_t st = ham_cursor_find(m_cursor, k->get_handle(),
00511                         (r ? r->get_handle() : 0), flags);
00512       if (st)
00513         throw error(st);
00514     }
00515 
00517     void insert(key *k, record *r, ham_u32_t flags = 0) {
00518       ham_status_t st = ham_cursor_insert(m_cursor, k ? k->get_handle() : 0,
00519                           r ? r->get_handle() : 0, flags);
00520       if (st)
00521         throw error(st);
00522     }
00523 
00525     void erase(ham_u32_t flags = 0) {
00526       ham_status_t st = ham_cursor_erase(m_cursor, flags);
00527       if (st)
00528         throw error(st);
00529     }
00530 
00532     ham_u32_t get_duplicate_count(ham_u32_t flags = 0) {
00533       ham_u32_t c;
00534       ham_status_t st = ham_cursor_get_duplicate_count(m_cursor, &c, flags);
00535       if (st)
00536         throw error(st);
00537       return (c);
00538     }
00539 
00541     ham_u64_t get_record_size() {
00542       ham_u64_t s;
00543       ham_status_t st = ham_cursor_get_record_size(m_cursor, &s);
00544       if (st)
00545         throw error(st);
00546       return (s);
00547     }
00548 
00550     void close() {
00551       if (!m_cursor)
00552         return;
00553       ham_status_t st = ham_cursor_close(m_cursor);
00554       if (st)
00555         throw error(st);
00556       m_cursor = 0;
00557     }
00558 
00559   protected:
00560     /* Copy Constructor. Is protected and should not be used. */
00561     cursor(ham_cursor_t *c) {
00562       m_cursor = c;
00563     }
00564 
00565   private:
00566     ham_cursor_t *m_cursor;
00567 };
00568 
00574 class env {
00575   public:
00577     env()
00578       : m_env(0) {
00579     }
00580 
00582     ~env() {
00583       close();
00584     }
00585 
00587     void create(const char *filename, ham_u32_t flags = 0,
00588                 ham_u32_t mode = 0644, const ham_parameter_t *param = 0) {
00589       ham_status_t st = ham_env_create(&m_env, filename, flags, mode, param);
00590       if (st)
00591         throw error(st);
00592     }
00593 
00595     void open(const char *filename, ham_u32_t flags = 0,
00596                 const ham_parameter_t *param = 0) {
00597       ham_status_t st = ham_env_open(&m_env, filename, flags, param);
00598       if (st)
00599         throw error(st);
00600     }
00601 
00603     void flush(ham_u32_t flags = 0) {
00604       ham_status_t st = ham_env_flush(m_env, flags);
00605       if (st)
00606         throw error(st);
00607     }
00608 
00610     db create_db(ham_u16_t name, ham_u32_t flags = 0,
00611                 const ham_parameter_t *param = 0) {
00612       ham_db_t *dbh;
00613 
00614       ham_status_t st = ham_env_create_db(m_env, &dbh, name, flags, param);
00615       if (st)
00616         throw error(st);
00617 
00618       return (hamsterdb::db(dbh));
00619     }
00620 
00622     db open_db(ham_u16_t name, ham_u32_t flags = 0,
00623                 const ham_parameter_t *param = 0) {
00624       ham_db_t *dbh;
00625 
00626       ham_status_t st = ham_env_open_db(m_env, &dbh, name, flags, param);
00627       if (st)
00628         throw error(st);
00629 
00630       return (hamsterdb::db(dbh));
00631     }
00632 
00634     void rename_db(ham_u16_t oldname, ham_u16_t newname, ham_u32_t flags = 0) {
00635       ham_status_t st = ham_env_rename_db(m_env, oldname, newname, flags);
00636       if (st)
00637         throw error(st);
00638     }
00639 
00641     void erase_db(ham_u16_t name, ham_u32_t flags = 0) {
00642       ham_status_t st = ham_env_erase_db(m_env, name, flags);
00643       if (st)
00644         throw error(st);
00645     }
00646 
00648     txn begin(const char *name = 0) {
00649       ham_txn_t *h;
00650       ham_status_t st = ham_txn_begin(&h, m_env, name, 0, 0);
00651       if (st)
00652         throw error(st);
00653       return (txn(h));
00654     }
00655 
00656 
00658     void close(ham_u32_t flags = 0) {
00659       if (!m_env)
00660         return;
00661       // disable auto-cleanup; all objects will be destroyed when 
00662       // going out of scope
00663       flags &= ~HAM_AUTO_CLEANUP;
00664       ham_status_t st = ham_env_close(m_env, flags);
00665       if (st)
00666         throw error(st);
00667       m_env = 0;
00668     }
00669 
00671     void get_parameters(ham_parameter_t *param) {
00672       ham_status_t st = ham_env_get_parameters(m_env, param);
00673       if (st)
00674         throw error(st);
00675     }
00676 
00678     std::vector<ham_u16_t> get_database_names() {
00679       ham_size_t count = 32;
00680       ham_status_t st;
00681       std::vector<ham_u16_t> v(count);
00682 
00683       for (;;) {
00684         st = ham_env_get_database_names(m_env, &v[0], &count);
00685         if (!st)
00686           break;
00687         if (st && st!=HAM_LIMITS_REACHED)
00688           throw error(st);
00689         count += 16;
00690         v.resize(count);
00691       }
00692 
00693       v.resize(count);
00694       return (v);
00695     }
00696 
00697   private:
00698     ham_env_t *m_env;
00699 };
00700 
00701 } // namespace hamsterdb
00702 
00707 #endif // HAMSTERDB_HPP__