// // DB2_db.cc // // DB2_db: Implements the Berkeley B-Tree database as a Database object // (including duplicate values to allow duplicate word entries) // // Part of the ht://Dig package // Copyright (c) 1999-2004 The ht://Dig Group // For copyright details, see the file COPYING in your distribution // or the GNU Library General Public License (LGPL) version 2 or later // // // $Id: DB2_db.cc,v 1.26 2004/05/28 13:15:20 lha Exp $ // #ifdef HAVE_CONFIG_H #include "htconfig.h" #endif /* HAVE_CONFIG_H */ #include #include #include #ifdef HAVE_STD #include #ifdef HAVE_NAMESPACES using namespace std; #endif #else #include #endif /* HAVE_STD */ #ifndef _MSC_VER /* _WIN32 */ #include #endif #include "DB2_db.h" #include "HtConfiguration.h" // Default cache size in kilobytes. // Maybe this should be an config option, just for easy testing and // determination for best system performance // NOTE: page size is 1KB - do not change!! #define CACHE_SIZE_IN_KB 64 //***************************************************************************** // DB2_db::DB2_db() // DB2_db::DB2_db() { isOpen = 0; _compare = 0; _prefix = 0; } //***************************************************************************** // DB2_db::~DB2_db() // DB2_db::~DB2_db() { Close(); } //***************************************************************************** // int DB2_db::Open(const char *filename, int flags, int mode) { // // Initialize the database environment. // if((dbenv = db_init((char *)NULL)) == 0) return NOTOK; if(CDB_db_create(&dbp, dbenv, 0) != 0) return NOTOK; if(_compare) dbp->set_bt_compare(dbp, _compare); if(_prefix) dbp->set_bt_prefix(dbp, _prefix); // // Open the database. // if((errno = dbp->open(dbp, filename, NULL, db_type, flags, mode)) == 0) { // // Acquire a cursor for the database. // if ((seqrc = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { seqerr = seqrc; Close(); return NOTOK; } isOpen = 1; return OK; } else { return NOTOK; } } //***************************************************************************** // int DB2_db::Close() // int DB2_db::Close() { if(isOpen) { // // Close cursor, database and clean up environment // (void)(dbcp->c_close)(dbcp); (void)(dbp->close)(dbp, 0); (void)(dbenv->close(dbenv, 0)); dbenv = 0; } isOpen = 0; return OK; } //***************************************************************************** // char *DB2_db::Get_Next(String &item, String &key) // char * DB2_db::Get_Next(String &item, String &key) { if (isOpen && !seqrc) { // // Return values // key = skey; lkey = skey; item = data; // // Search for the next record // DBT local_key; DBT local_data; memset(&local_key, 0, sizeof(DBT)); memset(&local_data, 0, sizeof(DBT)); local_key.data = skey.get(); local_key.size = skey.length(); seqrc = dbcp->c_get(dbcp, &local_key, &local_data, DB_NEXT); seqerr = seqrc; if(!seqrc) { data = 0; data.append((char*)local_data.data, (int)local_data.size); skey = 0; skey.append((char*)local_key.data, (int)local_key.size); } return lkey.get(); } else return 0; } //***************************************************************************** // void DB2_db::Start_Seq() // void DB2_db::Start_Seq(const String& key) { DBT local_key; DBT local_data; memset(&local_key, 0, sizeof(DBT)); memset(&local_data, 0, sizeof(DBT)); skey = key; local_key.data = skey.get(); local_key.size = skey.length(); if (isOpen && dbp) { // // Okay, get the first key. Use DB_SET_RANGE for finding partial // keys also. If you set it to DB_SET, and the words book, books // and bookstore do exists, it will find them if you specify // book*. However if you specify boo* if will not find // anything. Setting to DB_SET_RANGE will still find the `first' // word after boo* (which is book). // seqrc = dbcp->c_get(dbcp, &local_key, &local_data, DB_SET_RANGE); seqerr = seqrc; if(!seqrc) { data = 0; data.append((char*)local_data.data, (int)local_data.size); skey = 0; skey.append((char*)local_key.data, (int)local_key.size); } } } //***************************************************************************** // void DB2_db::Start_Get() // void DB2_db::Start_Get() { DBT local_key; DBT local_data; memset(&local_key, 0, sizeof(DBT)); memset(&local_data, 0, sizeof(DBT)); if (isOpen && dbp) { // // Okay, get the first key. Use DB_SET_RANGE for finding partial // keys also. If you set it to DB_SET, and the words book, books // and bookstore do exists, it will find them if you specify // book*. However if you specify boo* if will not find // anything. Setting to DB_SET_RANGE will still find the `first' // word after boo* (which is book). // seqrc = dbcp->c_get(dbcp, &local_key, &local_data, DB_FIRST); seqerr = seqrc; if(!seqrc) { data = 0; data.append((char*)local_data.data, (int)local_data.size); skey = 0; skey.append((char*)local_key.data, (int)local_key.size); } } } //***************************************************************************** // int DB2_db::Put(const String &key, const String &data) // int DB2_db::Put(const String &key, const String &data) { DBT k, d; memset(&k, 0, sizeof(DBT)); memset(&d, 0, sizeof(DBT)); if (!isOpen) return NOTOK; k.data = (char*)key.get(); k.size = key.length(); d.data = (char*)data.get(); d.size = data.length(); // // A 0 in the flags in put means replace, if you didn't specify DB_DUP // somewhere else... // return (dbp->put)(dbp, NULL, &k, &d, 0) == 0 ? OK : NOTOK; } //***************************************************************************** // int DB2_db::Get(const String &key, String &data) // int DB2_db::Get(const String &key, String &data) { DBT k, d; memset(&k, 0, sizeof(DBT)); memset(&d, 0, sizeof(DBT)); // // k arg of get should be const but is not. Harmless cast. // k.data = (char*)key.get(); k.size = key.length(); int rc = dbp->get(dbp, NULL, &k, &d, 0); if (rc) return NOTOK; data = 0; data.append((char *)d.data, d.size); return OK; } //***************************************************************************** // int DB2_db::Exists(const String &key) // int DB2_db::Exists(const String &key) { String data; if (!isOpen) return 0; return Get(key, data); } //***************************************************************************** // int DB2_db::Delete(const String &key) // int DB2_db::Delete(const String &key) { DBT k; memset(&k, 0, sizeof(DBT)); if (!isOpen) return 0; k.data = (char*)key.get(); k.size = key.length(); return (dbp->del)(dbp, NULL, &k, 0); } //***************************************************************************** // DB2_db *DB2_db::getDatabaseInstance() // DB2_db * DB2_db::getDatabaseInstance(DBTYPE) { return new DB2_db(); } //***************************************************************************** // void Error(const char *error_prefix, char *message); // void Error(const char *error_prefix, char *message) { // We don't do anything here, it's mostly a stub so we can set a breakpoint // for debugging purposes fprintf(stderr, "%s: %s\n", error_prefix, message); } //****************************************************************************** /* * db_init -- * Initialize the environment. Only returns a pointer */ DB_ENV * DB2_db::db_init(char *home) { DB_ENV *dbenv; char *progname = "DB2 problem..."; int error; if((error = CDB_db_env_create(&dbenv, 0)) != 0) { fprintf(stderr, "DB2_db: CDB_db_env_create %s\n", CDB_db_strerror(error)); return 0; } dbenv->set_errpfx(dbenv, progname); dbenv->set_errcall(dbenv, &Error); if((error = dbenv->open(dbenv, (const char*)home, NULL, DB_CREATE | DB_PRIVATE | DB_INIT_LOCK | DB_INIT_MPOOL, 0666)) != 0) { dbenv->err(dbenv, error, "open %s", (home ? home : "")); return 0; } return (dbenv); }