/*********************************************************************** * libdba - A database agent library * * Copyright (C) 2000,2001 Michael Brownlow * * * * This program is free software; you can redistribute it and/or modify* * it under the terms of the GNU General Public License as published by* * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * * For questions and comments, please email the author at: * * mike@wsmake.org * ***********************************************************************/ #include #include #include "dba_db.h" /* * DBA_DB_DB - SleepyCat DB */ #ifdef HAVE_TARGET_DB static int __dba_db_count = 0; int __dba_db_init __P((void)) { __dba_db_count = 0; return DBA_INIT_SUCCEED; } int __dba_db_open __P((DBA *dba)) { static int error; DB *tdb; error = db_create(&tdb, NULL, 0); error = tdb->open(tdb, dba->filename, NULL, DB_HASH, DB_CREATE, 0664); dba->db = tdb; if(error != 0) { __dba_print_error("`%s': (db_open error=`%d'; %s)\n", dba->filename, error, strerror(error)); __dba_print_error("Is the file really a Berkeley DB file?\n"); return 0; } __dba_print_debug("opened agent %#x (type=DB)\n", dba); __dba_db_count++; return 1; } int __dba_db_close __P((DBA *dba)) { DB *db; static int err; if(!dba) { __dba_print_error("internal attempt to free a NULL dba. " "well that's funny..."); } db = dba->db; __dba_print_debug("closing agent %#x (type=DB)\n", dba); if(!(err=db->close(db,0))) { return DBA_SUCCEED; } else { return err; } } void __dba_db_memsetDBT __P((DBT *dbt)) { memset(dbt, 0, sizeof(DBT)); } void __dba_db_freeDBT __P((DBT *dbt)) { dbt->data = __dba_free(dbt->data); assert(!dbt->data); } DBT *__dba_db_setDBTChar __P((DBT *dbt, const char *data)) { assert(data); __dba_db_memsetDBT(dbt); dbt->data = (char *)__dba_malloc(strlen(data) + 1); assert(dbt->data != 0); memset(dbt->data, 0, strlen(data) + 1); memcpy(dbt->data,data,strlen(data)); dbt->size = strlen(data) + 1; return dbt; } DBT *__dba_db_setDBTLong __P((DBT *dbt, const long data)) { __dba_db_memsetDBT(dbt); dbt->data = (long *)malloc(sizeof(long)); memcpy(dbt->data,&data,sizeof(data)); dbt->size = sizeof(data); return dbt; } int __dba_db_add __P((DBA *dba, int data_type, const char *addkey, ...)) { va_list ap; static int err = 0; DBT key; DBT val; DB *tmp = dba->db; long dt_long = 0; char *dt_string = NULL; assert(addkey); va_start(ap, addkey); __dba_print_debug("starting add\n"); __dba_db_setDBTChar(&key,addkey); switch(data_type) { case DBA_DT_LONG : dt_long = va_arg(ap, long); __dba_db_setDBTLong(&val,dt_long); break; case DBA_DT_STRING : dt_string = va_arg(ap, char *); __dba_db_setDBTChar(&val,dt_string); break; default : __dba_print_error("unknown type (%d)\n", data_type); __dba_db_freeDBT(&key); va_end(ap); return 0; } /* FIXME: allow options for setting flags */ if((err = tmp->put(tmp,NULL,&key,&val,DB_NOOVERWRITE))!=0) { if(err == DB_KEYEXIST) { __dba_print_warning("key `%s' already exists in database\n", addkey); } else { __dba_print_error("__dba_db_add: db->put: %s (%d)\n", strerror(err), err); } __dba_db_freeDBT(&key); __dba_db_freeDBT(&val); va_end(ap); return 0; } switch(data_type) { case DBA_DT_LONG : __dba_print_debug("added `%s':`%ld'\n", addkey, dt_long); break; case DBA_DT_STRING : __dba_print_debug("added `%s':`%s'\n", addkey, dt_string); break; } __dba_db_freeDBT(&val); __dba_db_freeDBT(&key); va_end(ap); __dba_print_debug("finished add\n"); return 1; } int __dba_db_set __P((DBA *dba, int data_type, const char *setkey, ...)) { va_list ap; DBT key; DBT val; int data = 0; DB *db = dba->db; long dt_long = 0; char *dt_string = NULL; assert(setkey); va_start(ap, setkey); __dba_db_setDBTChar(&key,setkey); __dba_db_memsetDBT(&val); data = db->get(db,NULL,&key,&val,0); if(data == 0) { switch(data_type) { case DBA_DT_LONG : dt_long = va_arg(ap, long); __dba_db_setDBTLong(&val,dt_long); break; case DBA_DT_STRING : dt_string = va_arg(ap, char *); __dba_db_setDBTChar(&val,dt_string); break; default : __dba_print_error("unknown type (%d)\n", data_type); __dba_db_freeDBT(&key); __dba_db_freeDBT(&val); va_end(ap); return 0; } db->put(db,NULL,&key,&val,0); } else { __dba_db_freeDBT(&key); va_end(ap); return 0; /* Could not find setkey */ } switch(data_type) { case DBA_DT_LONG : __dba_print_debug("set `%s':`%ld'\n", setkey, dt_long); break; case DBA_DT_STRING : __dba_print_debug("set `%s':`%s'\n", setkey, dt_string); break; } __dba_db_freeDBT(&key); __dba_db_freeDBT(&val); va_end(ap); return 1; } int __dba_db_del __P((DBA *dba, const char *delkey)) { DBT key; int data = 0; DB *db = dba->db; assert(delkey); __dba_db_setDBTChar(&key,delkey); data = db->del(db,NULL,&key,0); __dba_db_freeDBT(&key); return (data)?0:1; } void *__dba_db_get __P((DBA *dba, int data_type, const char *testkey, void *value)) { DBT key; DBT val; int data = 0; DB *db = dba->db; assert(testkey); if(dba->db!=NULL) { __dba_db_setDBTChar(&key,testkey); __dba_db_memsetDBT(&val); data = db->get(db,NULL,&key,&val,0); __dba_db_freeDBT(&key); if(data == DB_NOTFOUND) { __dba_print_error("key `%s' was not found in database\n", testkey); } else if(data) { __dba_print_error("__dba_db_get: db->get: %s (%d)\n", strerror(data), data); return NULL; } switch(data_type) { case DBA_DT_LONG : memcpy(value,val.data,val.size); break; case DBA_DT_STRING : value = (void *)__dba_malloc(val.size); if(value == NULL) { __dba_print_warning("couldn't allocate memory for dba_db_get.\n"); return NULL; } memset(value,0,val.size); memcpy(value,val.data,val.size); } if(data == 0) { return value; } else { /* This shouldn't happen, assert */ assert(1); } } return NULL; } int __dba_db_exists __P((DBA *dba, const char *testkey)) { DBT key; DBT val; int data=0; DB *db = dba->db; assert(testkey); if(__dba_db_setDBTChar(&key,testkey) == NULL) { return -1; } __dba_db_memsetDBT(&val); data = db->get(db,NULL,&key,&val,0); __dba_db_freeDBT(&key); if(data == DB_NOTFOUND) { return 0; } else { return 1; } return 0; } int __dba_db_register __P((DBA *dba)) { dba->open = (int (*)(DBA *))(__dba_db_open); dba->close = (int (*)(DBA *))(__dba_db_close); dba->add = (int (*)(DBA *, int, const char *, ...))(__dba_db_add); dba->set = (int (*)(DBA *, int, const char *, ...))(__dba_db_set); dba->del = (int (*)(DBA *, const char *))(__dba_db_del); dba->get = (void *(*)(DBA *, int, const char *, void *))(__dba_db_get); dba->exists = (int (*)(DBA *, const char *))(__dba_db_exists); return 1; } #endif