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