/* DCTC - a Direct Connect text clone for Linux * Copyright (C) 2001 Eric Prevoteau * * bdb.c: Copyright (C) Eric Prevoteau * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include "main.h" #include "bdb.h" /**************************/ /* BerkeleyDB environment */ /**************************/ DB_ENV *dbenv=NULL; DB *unwanted_user=NULL; /* berkeleyDB of all users we must ignore */ DB *seen_hub_db=NULL; /* berkeleyDB of all seen hubs */ static struct { DB **ptr; /* pointer on the DB handle associated to the db name */ char *db_name; int db_type; } db_list[]={ {&unwanted_user,"unwanted_user",DB_BTREE}, {&seen_hub_db,"seen_hub",DB_BTREE}, {NULL,NULL} }; /********************************************/ /* close dctc DBs and exit Berkeley library */ /********************************************/ void do_berkeley_exit(void) { int rt; if(dbenv!=NULL) { int i; i=0; while(db_list[i].db_name!=NULL) { if(*(db_list[i].ptr)!=NULL) { rt=(*(db_list[i].ptr))->close(*(db_list[i].ptr),0); if(rt!=0) { dbenv->err(dbenv,rt,"db_appexit(dbclose) fails"); if(rt==DB_RUNRECOVERY) { fprintf(stderr,"DB recovery must be performed now. Start db_recover on the database\n"); } } *(db_list[i].ptr)=NULL; } i++; } /* and finally, close the library */ rt=dbenv->close(dbenv,0); if(rt!=0) { dbenv->err(dbenv,rt,"db_appexit(close) fails"); if(rt==DB_RUNRECOVERY) { fprintf(stderr,"DB recovery must be performed now. Start db_recover on the database\n"); } } dbenv=NULL; } } /********************************************************************/ /* initialize berkeleyDB library and check/create and open dctc DBs */ /********************************************************************/ void do_berkeley_init(void) { char *t; int rt; struct stat st; dbenv=NULL; rt=db_env_create(&dbenv,0); if(rt!=0) { if(rt==DB_RUNRECOVERY) { fprintf(stderr,"DB recovery must be performed now. Start db_recover\n"); } else { perror("db_env_create"); } exit(1); } if(dbenv==NULL) { fprintf(stderr,"Out of memory.\n"); exit(1); } dbenv->set_errpfx(dbenv,"dc_gui"); t=g_strconcat(dctc_main_dir->str,"/","bDB",NULL); if(stat(t,&st)==-1) { if(mkdir(t,0777)!=0) { perror("mkdir"); fprintf(stderr,"Unable to create directory %s for database\n",t); exit(1); } } else { if(!S_ISDIR(st.st_mode)) { fprintf(stderr,"%s is not a directory\n",t); exit(1); } } rt=dbenv->open(dbenv,t,DB_CREATE|DB_INIT_LOCK|DB_THREAD|DB_INIT_MPOOL,0777); if(rt!=0) { dbenv->err(dbenv,rt,"db_appinit, open %s fails",t); if(rt==DB_RUNRECOVERY) { fprintf(stderr,"DB recovery must be performed now. Start db_recover -h %s\n",t); } do_berkeley_exit(); exit(1); } { /* open all wanted DB */ int i; i=0; while(db_list[i].db_name!=NULL) { db_create(db_list[i].ptr,dbenv,0); #ifndef BDB_V4 rt=(*(db_list[i].ptr))->open(*(db_list[i].ptr),db_list[i].db_name,NULL,db_list[i].db_type,DB_CREATE|DB_THREAD,0666); #else rt=(*(db_list[i].ptr))->open(*(db_list[i].ptr),NULL,db_list[i].db_name,NULL,db_list[i].db_type,DB_CREATE|DB_THREAD,0666); #endif if(rt!=0) { dbenv->err(dbenv,rt,"db_appinit, dbopen %s/%s fails",t,db_list[i].db_name); if(rt==DB_RUNRECOVERY) { fprintf(stderr,"DB recovery must be performed now. Start db_recover -h %s\n",t); } do_berkeley_exit(); exit(1); } i++; } } g_free(t); } /***************************/ /* get data of a given key */ /****************************************************************************/ /* output: 0=ok, !=0 not found */ /* if ok, *data_val contains the data (to free when no more useful) */ /* *data_len is the length of the data */ /****************************************************************************/ int get_key_data(DB *table, void *key_val, const int key_len, void **data_val, int *data_len) { DBT key; DBT data; int ret; memset(&key,0,sizeof(key)); memset(&data,0,sizeof(data)); key.data=key_val; key.size=key_len; data.flags=DB_DBT_MALLOC; ret=table->get(table,NULL,&key,&data,0); if(ret==0) { /* key found */ *data_val=data.data; *data_len=data.size; return 0; } else if(ret==DB_NOTFOUND) { return 1; } else if(ret==DB_RUNRECOVERY) { fprintf(stderr,"get_key_data: DB recovery must be performed now. Start db_recover.\n"); return 1; } else { fprintf(stderr,"get_key_data: unknown return code: %d\n",ret); dbenv->err(dbenv,ret,"db_appinit(get_key_data) fails"); return 1; } } /***************************/ /* set data of a given key */ /***************************/ /* output: 0=ok, !=0 error */ /***************************/ int set_key_data(DB *table, void *key_val, const int key_len, void *data_val, const int data_len) { DBT key; DBT data; int ret; memset(&key,0,sizeof(key)); memset(&data,0,sizeof(data)); key.data=key_val; key.size=key_len; data.data=data_val; data.size=data_len; ret=table->put(table,NULL,&key,&data,0); if(ret==0) { /* put ok */ return 0; } else if(ret==DB_RUNRECOVERY) { fprintf(stderr,"put_key_data: DB recovery must be performed now. Start db_recover.\n"); return 1; } else { fprintf(stderr,"put_key_data: unknown return code: %d\n",ret); dbenv->err(dbenv,ret,"db_appinit(set_key_data) fails"); return 1; } } /******************************/ /* del data and the given key */ /******************************/ /* output: 0=ok, !=0 error */ /***************************/ int del_key_data(DB *table, void *key_val, const int key_len) { DBT key; int ret; memset(&key,0,sizeof(key)); key.data=key_val; key.size=key_len; ret=table->del(table,NULL,&key,0); if(ret==0) { /* del ok */ return 0; } else if(ret==DB_NOTFOUND) { /* del ok */ return 0; } else if(ret==DB_RUNRECOVERY) { fprintf(stderr,"del_key_data: DB recovery must be performed now. Start db_recover.\n"); return 1; } else { fprintf(stderr,"del_key_data: unknown return code: %d\n",ret); return 1; } }