hamsterdb Embedded Database 1.1.14

hamsterdb.hpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005-2010 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) && !defined(UNDER_CE)
00035 #define _CRTDBG_MAP_ALLOC
00036 #include <crtdbg.h>
00037 #endif
00038 
00047 namespace ham {
00048 
00049 /*
00050  * forward declarations
00051  */
00052 class txn;
00053 class db;
00054 class env;
00055 
00061 class error {
00062 public:
00064     error(ham_status_t st) : m_errno(st) {
00065     };
00066 
00068     ham_status_t get_errno() const {
00069         return (m_errno);
00070     }
00071 
00073     const char *get_string() const {
00074         return (ham_strerror(m_errno));
00075     }
00076 
00077 private:
00078     ham_status_t m_errno;
00079 };
00080 
00086 class key {
00087 public:
00089     key(void *data=0, ham_size_t size=0, ham_u32_t flags=0) {
00090         memset(&m_key, 0, sizeof(m_key));
00091         m_key.data=data;
00092         m_key.size=(ham_u16_t)size;
00093         m_key.flags=flags;
00094         if (m_key.size != size) // check for overflow
00095             throw error(HAM_INV_KEYSIZE);
00096     }
00097 
00099     key(const key &other) : m_key(other.m_key) {
00100     }
00101 
00103     key &operator=(const key &other) 
00104     {
00105         /* TODO -- [i_a] copy key data; same for record; depends on USER_ALLOC flags, etc. */
00106         if (&other != this)
00107         {
00108             m_key=other.m_key;
00109         }
00110         return (*this);
00111     }
00112 
00114     void *get_data() const {
00115         return (m_key.data);
00116     }
00117 
00119     void set_data(void *data) {
00120         m_key.data=data;
00121     }
00122 
00124     ham_size_t get_size() const {
00125         return (m_key.size);
00126     }
00127 
00129     void set_size(ham_size_t size) {
00130         m_key.size=(ham_u16_t)size;
00131         if (m_key.size != size)
00132             throw error(HAM_INV_KEYSIZE);
00133     }
00134 
00136     template <class T>
00137     void set(T &t) {
00138         set_data(&t);
00139         set_size(sizeof(t));
00140     }
00141 
00143     ham_u32_t get_flags() const {
00144         return (m_key.flags);
00145     }
00146 
00148     void set_flags(ham_u32_t flags) {
00149         m_key.flags=flags;
00150     }
00151 
00153     ham_key_t *get_handle() {
00154         return (&m_key);
00155     }
00156 
00158     int get_approximate_match_type() {
00159         return (ham_key_get_approximate_match_type(&m_key));
00160     }
00161 
00162 
00163 private:
00164     ham_key_t m_key;
00165 };
00166 
00172 class record {
00173 public:
00175     record(void *data=0, ham_size_t size=0, ham_u32_t flags=0) {
00176         memset(&m_rec, 0, sizeof(m_rec));
00177         m_rec.data=data;
00178         m_rec.size=size;
00179         m_rec.flags=flags;
00180     }
00181 
00183     record(const record &other) : m_rec(other.m_rec) {
00184     }
00185 
00187     record &operator=(const record &other) {
00188         m_rec=other.m_rec;
00189         return (*this);
00190     }
00191 
00193     void *get_data() const {
00194         return (m_rec.data);
00195     }
00196 
00198     void set_data(void *data) {
00199         m_rec.data=data;
00200     }
00201 
00203     ham_size_t get_size() const {
00204         return (m_rec.size);
00205     }
00206 
00208     void set_size(ham_size_t size) {
00209         m_rec.size=size;
00210     }
00211 
00213     ham_u32_t get_flags() const {
00214         return (m_rec.flags);
00215     }
00216 
00218     void set_flags(ham_u32_t flags) {
00219         m_rec.flags=flags;
00220     }
00221 
00223     ham_record_t *get_handle() {
00224         return (&m_rec);
00225     }
00226 
00227 protected:
00228     ham_record_t m_rec;
00229 };
00230 
00231 
00237 class txn {
00238 public:
00240     txn(ham_txn_t *t=0) : m_txn(t) {
00241     }
00242 
00244     void abort() {
00245         ham_status_t st;
00246         st=ham_txn_abort(m_txn, 0);
00247         if (st)
00248             throw error(st);
00249     }
00250 
00252     void commit() {
00253         ham_status_t st;
00254         st=ham_txn_commit(m_txn, 0);
00255         if (st)
00256             throw error(st);
00257     }
00258 
00260     ham_txn_t *get_handle() {
00261         return (m_txn);
00262     }
00263 
00264 protected:
00265     ham_txn_t *m_txn;
00266 };
00267 
00268 
00274 class db
00275 {
00276 public:
00278     static void set_errhandler(ham_errhandler_fun f) {
00279         ham_set_errhandler(f);
00280     }
00281 
00283     static void get_version(ham_u32_t *major, ham_u32_t *minor,
00284                     ham_u32_t *revision) {
00285         ham_get_version(major, minor, revision);
00286     }
00287 
00289     static void get_license(const char **licensee, const char **product) {
00290         ham_get_license(licensee, product);
00291     }
00292 
00294     db() : m_db(0) {
00295     }
00296 
00298     ~db() {
00299         close();
00300     }
00301 
00308     db &operator=(const db &other) {
00309         db &rhs=(db &)other;
00310         if (this==&other)
00311             return (*this);
00312         close();
00313         m_db=rhs.m_db;
00314         rhs.m_db=0; 
00315         return (*this);
00316     }
00317 
00319     void create(const char *filename, ham_u32_t flags=0,
00320             ham_u32_t mode=0644, const ham_parameter_t *param=0) {
00321         ham_status_t st;
00322         if (!m_db) {
00323             st=ham_new(&m_db);
00324             if (st)
00325                 throw error(st);
00326         }
00327         st=ham_create_ex(m_db, filename, flags, mode, param);
00328         if (st)
00329             throw error(st);
00330     }
00331 
00333     void open(const char *filename, ham_u32_t flags=0,
00334             const ham_parameter_t *param=0) {
00335         ham_status_t st;
00336         if (!m_db) {
00337             st=ham_new(&m_db);
00338             if (st)
00339                 throw error(st);
00340         }
00341         st=ham_open_ex(m_db, filename, flags, param);
00342         if (st)
00343             throw error(st);
00344     }
00345 
00347     ham_status_t get_error() {
00348         if (!m_db)
00349             return (HAM_NOT_INITIALIZED);
00350         return (ham_get_error(m_db));
00351     }
00352 
00354     txn begin() {
00355         ham_txn_t *h;
00356         ham_status_t st=ham_txn_begin(&h, get_handle(), 0);
00357         if (st)
00358             throw error(st);
00359         return (txn(h));
00360     }
00361 
00363     void set_prefix_compare_func(ham_prefix_compare_func_t foo) {
00364         ham_status_t st=ham_set_prefix_compare_func(m_db, foo);
00365         if (st)
00366             throw error(st);
00367     }
00368 
00370     void set_compare_func(ham_compare_func_t foo) {
00371         ham_status_t st=ham_set_compare_func(m_db, foo);
00372         if (st)
00373             throw error(st);
00374     }
00375 
00377     void enable_compression(ham_u32_t level, ham_u32_t flags=0) {
00378         ham_status_t st=ham_enable_compression(m_db, level, flags);
00379         if (st)
00380             throw error(st);
00381     }
00382 
00384     record find(txn *t, key *k, ham_u32_t flags=0) {
00385         record r;
00386         ham_status_t st=ham_find(m_db, 
00387                 t ? t->get_handle() : 0, 
00388                 k ? k->get_handle() : 0,
00389                 r.get_handle(), flags);
00390         if (st)
00391             throw error(st);
00392         return (r);
00393     }
00394 
00396     record find(key *k, ham_u32_t flags=0) {
00397         return (find(0, k, flags));
00398     }
00399 
00401     void insert(txn *t, key *k, record *r, ham_u32_t flags=0) {
00402         ham_status_t st=ham_insert(m_db, 
00403                 t ? t->get_handle() : 0, 
00404                 k ? k->get_handle() : 0, 
00405                 r ? r->get_handle() : 0, flags);
00406         if (st)
00407             throw error(st);
00408     }
00409 
00411     void insert(key *k, record *r, ham_u32_t flags=0) {
00412         insert(0, k, r, flags);
00413     }
00414 
00416     void erase(key *k, ham_u32_t flags=0) {
00417         erase(0, k, flags);
00418     }
00419 
00421     void erase(txn *t, key *k, ham_u32_t flags=0) {
00422         ham_status_t st=ham_erase(m_db, 
00423                 t ? t->get_handle() : 0, 
00424                 k ? k->get_handle() : 0, flags);
00425         if (st)
00426             throw error(st);
00427     }
00428 
00430     void flush(ham_u32_t flags=0) {
00431         ham_status_t st=ham_flush(m_db, flags);
00432         if (st)
00433             throw error(st);
00434     }
00435 
00437     ham_u64_t get_key_count(ham_txn_t *txn=0, ham_u32_t flags=0) {
00438         ham_u64_t count=0;
00439         ham_status_t st=ham_get_key_count(m_db, txn, flags, &count);
00440         if (st)
00441             throw error(st);
00442         return (count);
00443     }
00444 
00446     void get_parameters(ham_parameter_t *param) {
00447         ham_status_t st=ham_get_parameters(m_db, param);
00448         if (st)
00449             throw error(st);
00450     }
00451 
00453     void close(ham_u32_t flags=0) {
00454         if (!m_db)
00455             return;
00456         ham_status_t st=ham_close(m_db, flags);
00457         if (st)
00458             throw error(st);
00459         st=ham_delete(m_db);
00460         if (st)
00461             throw error(st);
00462         m_db=0;
00463     }
00464 
00466     ham_db_t *get_handle() {
00467         return (m_db);
00468     }
00469 
00470 protected:
00471     friend class env;
00472 
00473     /* Copy Constructor. Is protected and should not be used. */
00474     db(ham_db_t *db) : m_db(db) {
00475     }
00476 
00477 private:
00478     ham_db_t *m_db;
00479 };
00480 
00481 
00487 class cursor
00488 {
00489 public:
00491     cursor(db *db=0, txn *t=0, ham_u32_t flags=0)
00492     :   m_cursor(0) {
00493         create(db, t, flags);
00494     }
00495 
00497     cursor(txn *t, db *db=0, ham_u32_t flags=0)
00498     :   m_cursor(0) {
00499         create(db, t, flags);
00500     }
00501 
00503     ~cursor() {
00504         close();
00505     }
00506 
00508     void create(db *db, txn *t=0, ham_u32_t flags=0) {
00509         if (m_cursor)
00510             close();
00511         if (db) {
00512             ham_status_t st=ham_cursor_create(db->get_handle(), 
00513                     t ? t->get_handle() : 0, 
00514                     flags, &m_cursor);
00515             if (st)
00516                 throw error(st);
00517         }
00518     }
00519 
00521     cursor clone() {
00522         ham_cursor_t *dest;
00523         ham_status_t st=ham_cursor_clone(m_cursor, &dest);
00524         if (st)
00525             throw error(st);
00526         return (cursor(dest));
00527     }
00528 
00530     void move(key *k, record *r, ham_u32_t flags=0) {
00531         ham_status_t st=ham_cursor_move(m_cursor, k ? k->get_handle() : 0,
00532                         r ? r->get_handle() : 0, flags);
00533         if (st)
00534             throw error(st);
00535     }
00536 
00538     void move_first(key *k=0, record *r=0) {
00539         move(k, r, HAM_CURSOR_FIRST);
00540     }
00541 
00543     void move_last(key *k=0, record *r=0) {
00544         move(k, r, HAM_CURSOR_LAST);
00545     }
00546 
00548     void move_next(key *k=0, record *r=0) {
00549         move(k, r, HAM_CURSOR_NEXT);
00550     }
00551 
00553     void move_previous(key *k=0, record *r=0) {
00554         move(k, r, HAM_CURSOR_PREVIOUS);
00555     }
00556 
00558     void overwrite(record *r, ham_u32_t flags=0) {
00559         ham_status_t st=ham_cursor_overwrite(m_cursor, 
00560                         r ? r->get_handle() : 0, flags);
00561         if (st)
00562             throw error(st);
00563     }
00564 
00566     void find(key *k, ham_u32_t flags=0) {
00567         ham_status_t st=ham_cursor_find(m_cursor, k->get_handle(), flags);
00568         if (st)
00569             throw error(st);
00570     }
00571 
00573     void find_ex(key *k, record *r, ham_u32_t flags=0) {
00574         ham_status_t st=ham_cursor_find_ex(m_cursor, k->get_handle(), 
00575                         (r ? r->get_handle() : 0), flags);
00576         if (st)
00577             throw error(st);
00578     }
00579 
00581     void insert(key *k, record *r, ham_u32_t flags=0) {
00582         ham_status_t st=ham_cursor_insert(m_cursor, k ? k->get_handle() : 0,
00583                         r ? r->get_handle() : 0, flags);
00584         if (st)
00585             throw error(st);
00586     }
00587 
00589     void erase(ham_u32_t flags=0) {
00590         ham_status_t st=ham_cursor_erase(m_cursor, flags);
00591         if (st)
00592             throw error(st);
00593     }
00594 
00596     ham_u32_t get_duplicate_count(ham_u32_t flags=0) {
00597         ham_u32_t c;
00598         ham_status_t st=ham_cursor_get_duplicate_count(m_cursor, &c, flags);
00599         if (st)
00600             throw error(st);
00601         return (c);
00602     }
00603 
00605     ham_u64_t get_record_size() {
00606         ham_u64_t s;
00607         ham_status_t st=ham_cursor_get_record_size(m_cursor, &s);
00608         if (st)
00609             throw error(st);
00610         return (s);
00611     }
00612 
00614     void close() {
00615         if (!m_cursor)
00616             return;
00617         ham_status_t st=ham_cursor_close(m_cursor);
00618         if (st)
00619             throw error(st);
00620         m_cursor=0;
00621     }
00622 
00623 protected:
00624     /* Copy Constructor. Is protected and should not be used. */
00625     cursor(ham_cursor_t *c) {
00626         m_cursor=c;
00627     }
00628 
00629 private:
00630     ham_cursor_t *m_cursor;
00631 };
00632 
00638 class env
00639 {
00640 public:
00642     env() : m_env(0) {
00643     }
00644 
00646     ~env() {
00647         close();
00648     }
00649 
00651     void create(const char *filename, ham_u32_t flags=0,
00652             ham_u32_t mode=0644, const ham_parameter_t *param=0) {
00653         ham_status_t st;
00654         if (!m_env) {
00655             st=ham_env_new(&m_env);
00656             if (st)
00657                 throw error(st);
00658         }
00659         st=ham_env_create_ex(m_env, filename, flags, mode, param);
00660         if (st)
00661             throw error(st);
00662     }
00663 
00665     void open(const char *filename, ham_u32_t flags=0,
00666             const ham_parameter_t *param=0) {
00667         ham_status_t st;
00668         if (!m_env) {
00669             st=ham_env_new(&m_env);
00670             if (st)
00671                 throw error(st);
00672         }
00673         st=ham_env_open_ex(m_env, filename, flags, param);
00674         if (st)
00675             throw error(st);
00676     }
00677 
00679     db create_db(ham_u16_t name, ham_u32_t flags=0, 
00680             const ham_parameter_t *param=0) {
00681         ham_status_t st;
00682         ham_db_t *dbh;
00683 
00684         st=ham_new(&dbh);
00685         if (st)
00686             throw error(st);
00687         st=ham_env_create_db(m_env, dbh, name, flags, param);
00688         if (st) {
00689             ham_delete(dbh);
00690             throw error(st);
00691         }
00692 
00693         return (ham::db(dbh));
00694     }
00695 
00697     db open_db(ham_u16_t name, ham_u32_t flags=0, 
00698             const ham_parameter_t *param=0) {
00699         ham_status_t st;
00700         ham_db_t *dbh;
00701 
00702         st=ham_new(&dbh);
00703         if (st)
00704             throw error(st);
00705         st=ham_env_open_db(m_env, dbh, name, flags, param);
00706         if (st) {
00707             ham_delete(dbh);
00708             throw error(st);
00709         }
00710 
00711         return (ham::db(dbh));
00712     }
00713 
00715     void rename_db(ham_u16_t oldname, ham_u16_t newname, ham_u32_t flags=0) {
00716         ham_status_t st=ham_env_rename_db(m_env, oldname, newname, flags);
00717         if (st)
00718             throw error(st);
00719     }
00720 
00722     void erase_db(ham_u16_t name, ham_u32_t flags=0) {
00723         ham_status_t st=ham_env_erase_db(m_env, name, flags);
00724         if (st)
00725             throw error(st);
00726     }
00727 
00731     void close(void) {
00732         if (!m_env)
00733             return;
00734         ham_status_t st=ham_env_close(m_env, 0);
00735         if (st)
00736             throw error(st);
00737         st=ham_env_delete(m_env);
00738         if (st)
00739             throw error(st);
00740         m_env=0;
00741     }
00742 
00744     void get_parameters(ham_parameter_t *param) {
00745         ham_status_t st=ham_env_get_parameters(m_env, param);
00746         if (st)
00747             throw error(st);
00748     }
00749 
00751     void enable_encryption(ham_u8_t key[16], ham_u32_t flags=0) {
00752         ham_status_t st=ham_env_enable_encryption(m_env, key, flags);
00753         if (st)
00754             throw error(st);
00755     }
00756 
00758     std::vector<ham_u16_t> get_database_names(void) {
00759         ham_size_t count=32;
00760         ham_status_t st;
00761         std::vector<ham_u16_t> v(count);
00762 
00763         for(;;) {
00764             st=ham_env_get_database_names(m_env, &v[0], &count);
00765             if (!st)
00766                 break;
00767             if (st && st!=HAM_LIMITS_REACHED)
00768                 throw error(st);
00769             count+=16;
00770             v.resize(count);
00771         }
00772 
00773         v.resize(count);
00774         return (v);
00775     }
00776 
00777 private:
00778     ham_env_t *m_env;
00779 };
00780 
00781 }; // namespace ham
00782 
00787 #endif // HAMSTERDB_HPP__