hamsterdb Embedded Database 1.1.13
|
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 void close() { 00606 if (!m_cursor) 00607 return; 00608 ham_status_t st=ham_cursor_close(m_cursor); 00609 if (st) 00610 throw error(st); 00611 m_cursor=0; 00612 } 00613 00614 protected: 00615 /* Copy Constructor. Is protected and should not be used. */ 00616 cursor(ham_cursor_t *c) { 00617 m_cursor=c; 00618 } 00619 00620 private: 00621 ham_cursor_t *m_cursor; 00622 }; 00623 00629 class env 00630 { 00631 public: 00633 env() : m_env(0) { 00634 } 00635 00637 ~env() { 00638 close(); 00639 } 00640 00642 void create(const char *filename, ham_u32_t flags=0, 00643 ham_u32_t mode=0644, const ham_parameter_t *param=0) { 00644 ham_status_t st; 00645 if (!m_env) { 00646 st=ham_env_new(&m_env); 00647 if (st) 00648 throw error(st); 00649 } 00650 st=ham_env_create_ex(m_env, filename, flags, mode, param); 00651 if (st) 00652 throw error(st); 00653 } 00654 00656 void open(const char *filename, ham_u32_t flags=0, 00657 const ham_parameter_t *param=0) { 00658 ham_status_t st; 00659 if (!m_env) { 00660 st=ham_env_new(&m_env); 00661 if (st) 00662 throw error(st); 00663 } 00664 st=ham_env_open_ex(m_env, filename, flags, param); 00665 if (st) 00666 throw error(st); 00667 } 00668 00670 db create_db(ham_u16_t name, ham_u32_t flags=0, 00671 const ham_parameter_t *param=0) { 00672 ham_status_t st; 00673 ham_db_t *dbh; 00674 00675 st=ham_new(&dbh); 00676 if (st) 00677 throw error(st); 00678 st=ham_env_create_db(m_env, dbh, name, flags, param); 00679 if (st) { 00680 ham_delete(dbh); 00681 throw error(st); 00682 } 00683 00684 return (ham::db(dbh)); 00685 } 00686 00688 db open_db(ham_u16_t name, ham_u32_t flags=0, 00689 const ham_parameter_t *param=0) { 00690 ham_status_t st; 00691 ham_db_t *dbh; 00692 00693 st=ham_new(&dbh); 00694 if (st) 00695 throw error(st); 00696 st=ham_env_open_db(m_env, dbh, name, flags, param); 00697 if (st) { 00698 ham_delete(dbh); 00699 throw error(st); 00700 } 00701 00702 return (ham::db(dbh)); 00703 } 00704 00706 void rename_db(ham_u16_t oldname, ham_u16_t newname, ham_u32_t flags=0) { 00707 ham_status_t st=ham_env_rename_db(m_env, oldname, newname, flags); 00708 if (st) 00709 throw error(st); 00710 } 00711 00713 void erase_db(ham_u16_t name, ham_u32_t flags=0) { 00714 ham_status_t st=ham_env_erase_db(m_env, name, flags); 00715 if (st) 00716 throw error(st); 00717 } 00718 00722 void close(void) { 00723 if (!m_env) 00724 return; 00725 ham_status_t st=ham_env_close(m_env, 0); 00726 if (st) 00727 throw error(st); 00728 st=ham_env_delete(m_env); 00729 if (st) 00730 throw error(st); 00731 m_env=0; 00732 } 00733 00735 void get_parameters(ham_parameter_t *param) { 00736 ham_status_t st=ham_env_get_parameters(m_env, param); 00737 if (st) 00738 throw error(st); 00739 } 00740 00742 void enable_encryption(ham_u8_t key[16], ham_u32_t flags=0) { 00743 ham_status_t st=ham_env_enable_encryption(m_env, key, flags); 00744 if (st) 00745 throw error(st); 00746 } 00747 00749 std::vector<ham_u16_t> get_database_names(void) { 00750 ham_size_t count=32; 00751 ham_status_t st; 00752 std::vector<ham_u16_t> v(count); 00753 00754 for(;;) { 00755 st=ham_env_get_database_names(m_env, &v[0], &count); 00756 if (!st) 00757 break; 00758 if (st && st!=HAM_LIMITS_REACHED) 00759 throw error(st); 00760 count+=16; 00761 v.resize(count); 00762 } 00763 00764 v.resize(count); 00765 return (v); 00766 } 00767 00768 private: 00769 ham_env_t *m_env; 00770 }; 00771 00772 }; // namespace ham 00773 00778 #endif // HAMSTERDB_HPP__