hamsterdb Embedded Database 1.1.14
|
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__