/*************************************************************************** Disk Based Hash library DBH exported functions. copyright Edscott Wilson Garcia 2002-2003 published under LGPL Public license You should have received a license copy along with this file. *************************************************************************/ int DBH_foreach_sweep(DBHashTable *node,DBHashFunc operate) { node->head_info->DBH_exit=0; if (operate) node->operate=operate; return DBH_newbarre(node,NULL,NULL,0); } int DBH_foreach_fanout(DBHashTable *node,DBHashFunc operate) { node->head_info->DBH_exit=0; if (operate) node->operate=operate; return DBH_newreversebarre(node,NULL,NULL,0); } /* Functions: */ int DBH_Size(DBHashTable * node,int record_length) { return (DBH_size(node,record_length)); } DBHashTable *DBH_create(char *archivo,unsigned char ramas) { DBHashTable *node; if (strlen(archivo)>255) ABORT3 node=(DBHashTable *)malloc(sizeof(DBHashTable)); if (node==NULL) return NULL; memset(node, 0, sizeof(DBHashTable)); node->database = fopen(archivo,"wb+"); if (node->database == NULL) {free (node); return NULL;} node->head_info = (header *)malloc(1024); #ifdef HAVE_MEMSET memset((void *)(node->head_info),0,1024); #else { int i; char *t; t=(char *)(node->head_info); for (i=0;i<1024;i++) *t=0; } #endif node->head_info->bof = 1024; node->head_info->n_limit=ramas; node->head_info->descending=0; node->head_info->sweep_erased=0; node->head_info->total_space = node->head_info->data_space=node->head_info->erased_space = 0; strcpy(node->head_info->version,DBH_FILE_VERSION); node->head_info->records=0; node->operate=DBH_operate; node->branch = (FILE_POINTER *)malloc(node->head_info->n_limit*sizeof(FILE_POINTER)); node->newbranch = (FILE_POINTER *)malloc(node->head_info->n_limit*sizeof(FILE_POINTER)); node->key=(unsigned char *)malloc(ramas); node->newkey=(unsigned char *)malloc(ramas); strcpy(node->head_info->archivo,archivo); node->head_info->membof=NULL; node->head_info->record_length=0; DBH_size(node,DBH_datasize); node->head_info->reservedA=0; node->bytes_userdata=0; node->head_info->writeOK=1; DBH_writeheader(node); fflush(node->database); return node; } /******************************************************************************/ #define COPYRIGHT "DBH file format is copyright 2000-2002 Edscott Wilson Garcia." int DBH_writeheader(DBHashTable *node) { if (!node) {WARNING8; return ERROR_VALUE;} strcpy((char *)(node->head_info->padding),COPYRIGHT); #ifdef TURN node->head_info->bof=DBH_turnaround(node->head_info->bof); node->head_info->record_length=DBH_turnaround(node->head_info->record_length); node->head_info->total_space=DBH_turnaround(node->head_info->total_space); node->head_info->data_space=DBH_turnaround(node->head_info->data_space); node->head_info->erased_space=DBH_turnaround(node->head_info->erased_space); node->head_info->records=DBH_turnaround(node->head_info->records); node->head_info->reservedA=DBH_turnaround(node->head_info->reservedA); node->head_info->reservedB=DBH_turnaround(node->head_info->reservedB); node->head_info->fractalidad=DBH_turnaround(node->head_info->fractalidad); #endif if (fseek(node->database,0L,SEEK_SET)) return ERROR_VALUE; if (fwrite(node->head_info,1024,1,node->database) != 1) return ERROR_VALUE; #ifdef TURN node->head_info->bof=DBH_turnaround(node->head_info->bof); node->head_info->record_length=DBH_turnaround(node->head_info->record_length); node->head_info->total_space=DBH_turnaround(node->head_info->total_space); node->head_info->data_space=DBH_turnaround(node->head_info->data_space); node->head_info->erased_space=DBH_turnaround(node->head_info->erased_space); node->head_info->records=DBH_turnaround(node->head_info->records); node->head_info->reservedA=DBH_turnaround(node->head_info->reservedA); node->head_info->reservedB=DBH_turnaround(node->head_info->reservedB); node->head_info->fractalidad=DBH_turnaround(node->head_info->fractalidad); #endif return 1; } /************************************************************************************/ int DBH_info(DBHashTable *node) { if (!node) {WARNING8; return ERROR_VALUE;} fseek(node->database,0L,SEEK_END); fprintf(stdout,"\nEnd of DBHashTable (ftell()) = %ld\n", ftell(node->database)); fprintf(stdout,"\nDBHashTable header size = %ld", (long)sizeof(header)); fprintf(stdout, "\nheader:\n\ version=%s\n\ keylength=%d\n\ first record position=%ld\n\ maximum record length=%ld\n\ records=%ld\n\ total_space=%ld\n\ data_space=%ld\n\ erased_space=%ld\n\ format_space=%ld\n\ ", node->head_info->version, DBH_KEYLENGTH(node), (long)node->head_info->bof, (long)DBH_MAXIMUM_RECORD_SIZE(node), (long)DBH_RECORDS(node), (long)DBH_TOTAL_SPACE(node), (long)DBH_DATA_SPACE(node), (long)DBH_ERASED_SPACE(node), (long)DBH_FORMAT_SPACE(node)); return 1; } /****************************************************************************/ DBHashTable *DBH_open(char *archivo){return (DBH_open_S(archivo,WRITE));} DBHashTable *DBH_openR(char *archivo){return (DBH_open_S(archivo,READ));} int DBH_close(DBHashTable * node) { if (node==NULL) return 0; if (node->head_info->writeOK) DBH_writeheader(node); fclose(node->database); free(node->data); free(node->newdata); free(node->branch); free(node->newbranch); free(node->key); free(node->newkey); free(node->head_info); free(node); return 1; } /****************************************************************************/ unsigned char DBH_load_address(DBHashTable *node,FILE_POINTER currentseek) { unsigned char i; if (node==NULL) return ERROR_VALUE; if (currentseek == 0) return ERROR_VALUE; node->head_info->reservedB=currentseek; for (i = 1;i <= node->head_info->n_limit;i++) node->branch[i-1] = 0; if (fseek(node->database,currentseek,SEEK_SET)) return ERROR_VALUE; if (!DBH_read(OLD,node,1)) return ERROR_VALUE; return node->branches; } /*********************************************************************************/ /* this function will also load erased values, except that it will * return false for them. The currentseek value will be placed in * node->currentseek, however */ FILE_POINTER DBH_load(DBHashTable *node) { int i; int j; FILE_POINTER *fp; unsigned char *tmp1,*tmp2; if (node==NULL) return ERROR_VALUE; /* before loading, clean erased flag, so it will have a * valid value before function returns ERROR_VALUE */ SET_UNERASED; fp=DBH_locate(node); node->head_info->reservedB=CURRENTSEEK; if (!CURRENTSEEK) return ERROR_VALUE; /* don't toggle erased yet! Read the node anyways!*/ /*if (ERASED){TOGGLE_ERASE; return ERROR_VALUE;}*/ node->bytes_userdata = node->newbytes_userdata; node->branches = node->newbranches; tmp1=node->key; tmp2=node->newkey; for (j=0;jhead_info->n_limit;j++)tmp1[j]=tmp2[j]; tmp1=(unsigned char *)node->data; tmp2=(unsigned char *)node->newdata; for (i=0;inewbytes_userdata;i++)tmp1[i]=tmp2[i]; /* must look for CURRENTSEEK, (at node->current_seek) if this condition occurs: */ if (ERASED){return ERROR_VALUE;} return CURRENTSEEK; } /****************************************************************************/ FILE_POINTER DBH_find(DBHashTable *node,int keys) { FILE_POINTER *fp; if (node==NULL) return ERROR_VALUE; fp=DBH_locateT(node,keys); if (!CURRENTSEEK) return ERROR_VALUE; node->bytes_userdata = node->newbytes_userdata; node->branches = node->newbranches; return CURRENTSEEK; } /***************************************************************************/ FILE_POINTER DBH_load_parent(DBHashTable *node) { FILE_POINTER *fp; if (node==NULL) return ERROR_VALUE; fp=DBH_locate(node); if (!CURRENTSEEK || !LASTSEEK) return ERROR_VALUE; return DBH_load_address(node,LASTSEEK); } /**********************************************************************/ FILE_POINTER DBH_load_child(DBHashTable *node,unsigned char key_index) { FILE_POINTER *fp,child_address; if (node==NULL) return ERROR_VALUE; fp=DBH_locate(node); if (!CURRENTSEEK) return ERROR_VALUE; if (key_index >= node->newbranches) return ERROR_VALUE; child_address = *(node->newbranch+key_index); return DBH_load_address(node,child_address); } /**********************************************************************/ /* update function will update erased records as well as unerased records, but if * an erased record is updated, it is automatically unerased */ FILE_POINTER DBH_update(DBHashTable * node) { FILE_POINTER *fp; unsigned char j,caso; int i; if (node==NULL) return ERROR_VALUE; /* before updating, clean erased flag, so updated record will be automatically unerased * this allows reusing the erased space, although it introduces error in the tabulated * values of erased_space and total_space, but who cares, it's an approximation * anyways. */ SET_UNERASED; node->head_info->reservedC=0; fp=DBH_locate(node); if (CURRENTSEEK) { if (node->newbytes_userdata < node->bytes_userdata) { if (LASTSEEK) caso = PRESENTE_MENOR; else caso = PRESENTE_MENOR_BOF; } else caso = PRESENTE_MAYORIGUAL; } else { if (LASTSEEK) caso = NO_PRESENTE; else caso = ARCHIVO_VACIO; } node->flag=0; switch (caso) { case NO_PRESENTE: /* no esta en el archivo */ for (i=0;ihead_info->n_limit;i++) node->branch[i]=0; if (fseek(node->database,0L,SEEK_END)) return ERROR_VALUE; CURRENTSEEK = ftell(node->database); node->newbranches -= (unsigned char)CURR_BRANCH; node->head_info->data_space += node->bytes_userdata; node->head_info->total_space += (node->bytes_userdata+sizeof(FILE_POINTER)*node->newbranches+1+sizeof(FILE_POINTER)); if (!DBH_write(OLD,node,WRITEBRANCHES)) return ERROR_VALUE; if (!DBH_readBranches(node,LASTSEEK)) return ERROR_VALUE; node->newbranch[CURR_BRANCH] = CURRENTSEEK; DBH_updateBranch(node,LASTSEEK); node->head_info->records++; break; /*********************************/ case PRESENTE_MAYORIGUAL: /* no hay bronca con usar el mismo espacio de disco */ node->head_info->erased_space += (node->newbytes_userdata-node->bytes_userdata); node->head_info->data_space -= (node->newbytes_userdata-node->bytes_userdata); if (fseek(node->database,CURRENTSEEK,SEEK_SET)) return ERROR_VALUE; if (!DBH_write(OLD,node,DONTWRITEBRANCHES)) return ERROR_VALUE; break; /*********************************/ case PRESENTE_MENOR_BOF: /* no cabe en el registro, y peor, es el primer registro del archivo */ node->head_info->erased_space += (node->newbytes_userdata); node->head_info->data_space += (node->bytes_userdata-node->newbytes_userdata); node->head_info->total_space += (node->bytes_userdata+sizeof(FILE_POINTER)*node->newbranches+1+sizeof(FILE_POINTER)); if (fseek(node->database,0L,SEEK_END)) return ERROR_VALUE; node->head_info->bof = ftell(node->database); if (!DBH_write(NEW,node,WRITEBRANCHES)) return ERROR_VALUE; DBH_writeheader(node); break; /*********************************/ case PRESENTE_MENOR: /* no cabe en el registro */ { unsigned char ramas; node->head_info->erased_space += (node->newbytes_userdata); node->head_info->data_space += (node->bytes_userdata-node->newbytes_userdata); node->head_info->total_space += (node->bytes_userdata+sizeof(FILE_POINTER)*node->newbranches+1+sizeof(FILE_POINTER)); if (fseek(node->database,0L,SEEK_END)) return ERROR_VALUE; CURRENTSEEK = ftell(node->database); j = node->newbranches; if (!DBH_write(NEW,node,WRITEBRANCHES)) return ERROR_VALUE; ramas=DBH_readBranches(node,LASTSEEK); if (!ramas) return ERROR_VALUE; node->newbranch[ramas-j+CURR_BRANCH] = CURRENTSEEK; DBH_updateBranch(node,LASTSEEK); } break; /*********************************/ case ARCHIVO_VACIO: for (i=0;ihead_info->n_limit;i++) node->branch[i]=0; if (fseek(node->database,(CURRENTSEEK=node->head_info->bof),SEEK_SET)) return ERROR_VALUE; node->newbranches = node->head_info->n_limit; node->head_info->data_space += node->bytes_userdata; node->head_info->total_space +=(node->bytes_userdata+sizeof(FILE_POINTER)*node->newbranches+1+sizeof(FILE_POINTER)); if (!DBH_write(OLD,node,WRITEBRANCHES)) return ERROR_VALUE; node->head_info->records++; break; /*********************************/ } return CURRENTSEEK; } /****************************************************************************/ int DBH_erase(DBHashTable * node) { FILE_POINTER currentseek; if (node==NULL) return ERROR_VALUE; currentseek=DBH_load(node); if (!currentseek) /* will return false if record is already ERASED */ return ERROR_VALUE; TOGGLE_ERASE; /* set the erased bit on*/ /* set file pointer at record flag byte */ fseek(node->database,currentseek+1,SEEK_SET); /* write the flag to the file */ if (fwrite(&(node->flag),1,1,node->database) != 1) { return ERROR_VALUE; } /* update file header information */ node->head_info->data_space -= node->bytes_userdata; node->head_info->erased_space += (node->bytes_userdata); DBH_writeheader(node); return 1; } /****************************************************************************/ int DBH_unerase(DBHashTable * node) { FILE_POINTER currentseek,*fp; if (node==NULL) return ERROR_VALUE; fp=DBH_locate(node); /* this will return TRUE if record is already ERASED */ currentseek=fp[0]; if (!currentseek) return ERROR_VALUE; /* got currentseek, now load it */ DBH_load_address(node,currentseek); /* found currentseek, now load it */ if (!ERASED) return ERROR_VALUE; /* hey man, nothing to do */ TOGGLE_ERASE; /* set file pointer at record flag byte */ fseek(node->database,currentseek+1,SEEK_SET); /* write the flag to the file */ if (fwrite(&(node->flag),1,1,node->database) != 1) { return ERROR_VALUE; } /* update file header information */ node->head_info->data_space += node->bytes_userdata; node->head_info->erased_space -= (node->bytes_userdata); DBH_writeheader(node); return 1; } /****************************************************************************/ int DBH_fanout(DBHashTable *node,DBHashFunc operate, unsigned char *key1,unsigned char *key2,unsigned char keylength){ if (!node) return ERROR_VALUE; if (operate) node->operate=operate; return DBH_newreversebarre(node,key1,key2,keylength); } int DBH_sweep(DBHashTable *node,DBHashFunc operate, unsigned char *key1,unsigned char *key2,unsigned char keylength){ if (!node) return ERROR_VALUE; if (operate) node->operate=operate; return DBH_newbarre(node,key1,key2,keylength); } void DBH_genkey0(unsigned char * numero,unsigned char orden,unsigned int n) { if (!n) { printf("DBH_genkey: value must be > \n"); return; } DBH_cuenta((unsigned char *)numero,orden,n); } /***************************************************************************************/ void DBH_genkey(unsigned char * numero,unsigned char orden,unsigned int n) { unsigned char i; int t; if (!n) { printf("DBH_genkey: value must be > \n"); return; } DBH_cuenta((unsigned char *)numero,orden,n); for (i=0;i \n"); return; } DBH_cuenta((unsigned char *)numero,orden,n); for (i=0;i'Z') {t=numero[i]; t+=6; numero[i]=(unsigned char)t;}} /* for (i=0;i'Z') numero[i] += 6;*/ } /***************************************************************************************/ void DBH_settempdir(char *dir) { if (!dir) return; if (DBH_tempdir != NULL) free(DBH_tempdir); DBH_tempdir=(char *)malloc(strlen(dir)+1); if (DBH_tempdir == NULL) {WARNING1; return;} strcpy(DBH_tempdir,dir); } /*******************************************************************/ char *DBH_randomfilename(char code) { time_t segundos; FILE_POINTER divisor; char *archivo; if (DBH_tempdir){ archivo=(char *)malloc(strlen(DBH_tempdir)+1+1+6+4+1); } else { archivo=(char *)malloc(strlen(DBH_TMP_DIR)+1+1+6+4+1); } time(&segundos); srand((unsigned) segundos); divisor=RAND_MAX/10000; if ((segundos=rand()/divisor)>100000L) ABORT7 /* sprintf(archivo,"%s%c%d.tmp",DBH_tempdir,code,segundos);*/ if (DBH_tempdir) sprintf(archivo,"%s/%c%ld.tmp",DBH_tempdir,code,(long)segundos); else sprintf(archivo,"%s/%c%ld.tmp",DBH_TMP_DIR,code,(long)segundos); return archivo; } /***************************************************************************************/ /* FIXME: look deeply into algorithm before releasing this function, * which affects the release of DBH_sort */ #define INSERT_ERROR { node->head_info->reservedC=0; return ERROR_VALUE;} FILE_POINTER DBH_insert(DBHashTable * node) { FILE_POINTER *fp; unsigned char caso; void *temp; int i; SWITCHED=0; if (node==NULL) return ERROR_VALUE; /* before updating, clean erased flag, so it will be automatically unerase. * see comment at DBH_update function */ SET_UNERASED; node->head_info->reservedC=1; fp=DBH_locateI(node); node->flag=0; if (CURRENTSEEK) caso = PRESENTE; else { if (LASTSEEK) caso = NO_PRESENTE; else caso = ARCHIVO_VACIO; } switch (caso) { case PRESENTE: if (fseek(node->database,CURRENTSEEK,SEEK_SET)) INSERT_ERROR if (!DBH_write(OLD,node,DONTWRITEBRANCHES)) INSERT_ERROR break; case NO_PRESENTE: for (i=0;ihead_info->n_limit;i++) node->branch[i]=0; if (fseek(node->database,0L,SEEK_END)) INSERT_ERROR CURRENTSEEK = ftell(node->database); node->newbranches -= (unsigned char)CURR_BRANCH; if (!DBH_write(OLD,node,WRITEBRANCHES)) INSERT_ERROR if(!DBH_readBranches(node,LASTSEEK)) INSERT_ERROR node->newbranch[CURR_BRANCH] = CURRENTSEEK; DBH_updateBranch(node,LASTSEEK); node->head_info->records++; break; case ARCHIVO_VACIO: for (i=0;ihead_info->n_limit;i++) node->branch[i]=0; if (fseek(node->database,(CURRENTSEEK=node->head_info->bof),SEEK_SET)) INSERT_ERROR; node->newbranches = node->head_info->n_limit; if (!DBH_write(OLD,node,WRITEBRANCHES)) INSERT_ERROR node->head_info->records++; break; } if (SWITCHED) { temp=node->data; node->data=node->newdata; node->newdata=temp; temp=(void *)node->key; node->key=node->newkey; node->newkey=(unsigned char *)temp; } node->head_info->reservedC=0; return CURRENTSEEK; } /*************************************************************************************/ /* LEVEL 2 functions */ DBHashTable * DBH_regen(DBHashTable *node) { void *temp, *newtemp; char *archivo2,archivo[256],archivobak[256]; DBHashTable * newnode; unsigned char *tempkey, *newtempkey; void (*fun)(struct DBHashTable *); if (!node) {WARNING8; return ERROR_VALUE;} archivo2=DBH_randomfilename('s'); strcpy(archivo,node->head_info->archivo); DBH_desnode=DBH_create(archivo2,node->head_info->n_limit); temp=DBH_desnode->data; DBH_desnode->data=node->data; newtemp=DBH_desnode->newdata; DBH_desnode->newdata=node->newdata; tempkey=DBH_desnode->key; DBH_desnode->key=node->key; newtempkey=DBH_desnode->newkey; DBH_desnode->newkey=node->newkey; DBH_desnode->head_info->fractalidad=node->head_info->fractalidad; fun=node->operate; node->operate=DBH_transfer; DBH_newbarre(node,NULL,NULL,0); DBH_desnode->data=temp; DBH_desnode->newdata=newtemp; DBH_desnode->key=tempkey; DBH_desnode->newkey=newtempkey; DBH_close(node); DBH_close(DBH_desnode); sprintf(archivobak,"%s.bak",archivo); remove(archivobak); if (rename(archivo2,archivo)<0) printf("\ncannot write to %s",archivo); newnode=DBH_open(archivo); free(archivo2); newnode->operate=fun; return newnode; } /***********************************************************************************/ DBHashTable * DBH_sort(DBHashTable *node,int direction) { void *temp, *newtemp; char *archivo,*archivo2; DBHashTable * newnode; unsigned char *tempkey, *newtempkey; void (*fun)(struct DBHashTable *); FILE_POINTER old; if (!node) {WARNING8; return ERROR_VALUE;} archivo=(char *)malloc(256); strcpy(archivo,node->head_info->archivo); archivo2=DBH_randomfilename('x'); old=DBH_size(NULL,node->head_info->record_length); DBH_desnode=DBH_create(archivo2,node->head_info->n_limit); DBH_desnode->head_info->fractalidad=node->head_info->fractalidad; DBH_size(NULL,old); if (direction) DBH_desnode->head_info->descending=0; else DBH_desnode->head_info->descending=1; DBH_writeheader(DBH_desnode); fun=node->operate; temp=DBH_desnode->data; DBH_desnode->data=node->data; newtemp=DBH_desnode->newdata; DBH_desnode->newdata=node->newdata; tempkey=DBH_desnode->key; DBH_desnode->key=node->key; newtempkey=DBH_desnode->newkey; DBH_desnode->newkey=node->newkey; node->operate=DBH_sortingS; DBH_newreversebarre(node,NULL,NULL,0); DBH_desnode->data=temp; DBH_desnode->newdata=newtemp; DBH_desnode->key=tempkey; DBH_desnode->newkey=newtempkey; DBH_close(node); DBH_close(DBH_desnode); remove(archivo); if (rename(archivo2,archivo)<0) printf("\ncannot write sort file"); newnode=DBH_open(archivo); free(archivo); free(archivo2); newnode->operate=fun; return newnode; } /***********************************************************************************/ #if 0 not yet released: Memory functions have not much use since the kernel based disk i/o cache is more efficient DBHashTable * DBH_regenMEM(DBHashTable *node) /* curiosamente, este se mostro mas lento que el orientado a disco */ { void *temp, *newtemp; char *archivo2,archivo[256]; DBHashTable * newnode; unsigned char *tempkey, *newtempkey; void (*fun)(struct DBHashTable *); if (!node) {WARNING8; return ERROR_VALUE;} archivo2=DBH_randomfilename('s'); strcpy(archivo,node->head_info->archivo); DBH_close(node); node=DBH_openmem(archivo); if (node==NULL) {ABORT2;} DBH_desnode=DBH_create(archivo2,node->head_info->n_limit); DBH_desnode->head_info->fractalidad=node->head_info->fractalidad; temp=DBH_desnode->data; DBH_desnode->data=node->data; newtemp=DBH_desnode->newdata; DBH_desnode->newdata=node->newdata; tempkey=DBH_desnode->key; DBH_desnode->key=node->key; newtempkey=DBH_desnode->newkey; DBH_desnode->newkey=node->newkey; fun=node->operate; node->operate=DBH_transfer; DBH_membarre(node,NULL,NULL,0); DBH_desnode->data=temp; DBH_desnode->newdata=newtemp; DBH_desnode->key=tempkey; DBH_desnode->newkey=newtempkey; DBH_close(node); DBH_close(DBH_desnode); remove("somod.bak"); if (rename(archivo,"somod.bak")<0) printf("\ncannot write somod.bak compact file"); if (rename(archivo2,archivo)<0) printf("\ncannot write compact file"); newnode=DBH_open(archivo); free(archivo2); newnode->operate=fun; return newnode; } /***********************************************************************************/ /*ojo, no hay funcion de mfind! -> que la base de disco debe estar abierta para que funcione*/ int DBH_membarre(DBHashTable *node,unsigned char *key1,unsigned char *key2,unsigned char keylength) { int i; FILE_POINTER pointer; if (!node) {WARNING8; return ERROR_VALUE;} node->head_info->DBH_exit=0; if (key1==NULL) { DBH_mbarre(node,node->head_info->bof,0);return 1;} if (key2!=NULL) { for (i=0;ihead_info->n_limit;i++) node->key[i]=key1[i]; for (i=0;ihead_info->n_limit;i++) if (key1[i]!=key2[i]) break; /* que pedo con ERASED?? Aqui no hay bronca */ if ((pointer=DBH_loadmem(node)) == ERROR_VALUE) return ERROR_VALUE; else { pointer=DBH_find(node,i); DBH_mbarre(node,pointer,node->head_info->n_limit-i); } } else if (keylength) { for (i=0;ikey[i]=key1[i]; pointer=DBH_find(node,keylength); if (pointer==ERROR_VALUE) return ERROR_VALUE; DBH_mbarre(node,pointer,node->head_info->n_limit-keylength); } return 1; } /***************************************************************************************/ DBHashTable * DBH_openmem(char *archivo) { /* calls opensomod() and putinmem() */ FILE *archin; FILE_POINTER filesize; DBHashTable * node; node = DBH_open(archivo); if (node==NULL) return NULL; /* putinmem() part */ archin=fopen(archivo,"rb"); if (archin==NULL) return NULL; fseek(archin,0,SEEK_END); filesize=ftell(archin); fseek(archin,0,SEEK_SET); node->head_info->membof = (unsigned char *)malloc(filesize); if (node->head_info->membof==NULL){ fclose(archin); DBH_close(node); return NULL; } fread(node->head_info->membof,filesize,1,archin); fclose(archin); return (node); } /***********************************************************************/ int DBH_closemem(DBHashTable *node) { if (node==NULL) return 0; if (node->head_info->membof==NULL) return 0; free(node->head_info->membof); return (DBH_close(node)); } /***********************************************************************/ /* Esta funcion hace lo mismo que load(), pero de la base de datos cargada en la memoria. */ FILE_POINTER DBH_loadmem(DBHashTable *node) { int i; FILE_POINTER currentseek; void * dat; unsigned char *tmp; FILE_POINTER seekspot; if (!node) {WARNING8; return ERROR_VALUE;} if (node->head_info->membof==NULL) return ERROR_VALUE; currentseek = node->head_info->bof; seekspot=currentseek; if (DBH_memread(1,node,seekspot)!=1) return ERROR_VALUE; loop: for (i = 0;i < node->newbranches;i++) if (*(node->key+(i+BRANCHOFF)) != *(node->newkey+(i+BRANCHOFF))) { if ((currentseek = *(node->newbranch+i)) == 0) return ERROR_VALUE; if (DBH_memread(1,node,currentseek)!=1) return ERROR_VALUE; goto loop; } node->bytes_userdata = node->newbytes_userdata; node->branches = node->newbranches; tmp=node->key;node->key=node->newkey;node->newkey=tmp; dat=node->data; node->data=node->newdata;node->newdata=dat; return currentseek; } /**************************************************************/ #endif #if 0 /*FIXME: what's this function about and doing here? */ DBHashTable * sortT(DBHashTable *node,unsigned char position, unsigned char length,unsigned char descending, unsigned char *key1,unsigned char *key2,unsigned char keylength,unsigned char totalkeylength) { void *temp, *newtemp; char *archivo="table.dat"; DBHashTable * newnode; void (*fun)(struct DBHashTable *); if (!node) {WARNING8; return ERROR_VALUE;} DBH_desnode=DBH_create(archivo,length); DBH_desnode->head_info->position=position; DBH_desnode->head_info->length=length; DBH_desnode->head_info->totalkeylength=totalkeylength; DBH_desnode->head_info->descending=descending; DBH_writeheader(DBH_desnode); temp=DBH_desnode->data; DBH_desnode->data=node->data; newtemp=DBH_desnode->newdata; DBH_desnode->newdata=node->newdata; fun=node->operate; node->operate=DBH_sorting; if (key1==NULL) DBH_newreversebarre(node,NULL,NULL,0); else { if (key2!=NULL) DBH_newreversebarre(node,key1,key2,0); else if (keylength) DBH_newreversebarre(node,key1,NULL,keylength); } node->operate=fun; DBH_desnode->data=temp; DBH_desnode->newdata=newtemp; DBH_close(DBH_desnode); newnode=DBH_open(archivo); /* printf("\ncomenzando etapa dos...");*/ newnode=DBH_regen(newnode); return newnode; } /****************************************************************/ #endif /* These DBH_Ezip+DBH_Eunzip might not merit being in the library. They are not even in * documentation. Please explain the reason of being in the docs. The map application * need them to cut down 25% of useless bits of graphic information. */ int DBH_Ezip(DBHashTable *node,unsigned int begin,unsigned int howmany){ char *source,*destination; void *tmp; unsigned int i; int *value; if (node->bytes_userdata==0) {printf ("Bytes_userdata=0\n");return 1;} if (begin+howmany*4 > (unsigned int)(node->bytes_userdata)) { printf ("Ezip incorrectly specified\n");return 1; } source=(char *)node->data, destination=(char *)node->newdata; for (i=0;i EZIP_NUMERO_MAXIMO) {printf("value %d not valid for EZIP\n",*value);} destination[0]=source[0], destination[1]=source[1], destination[2]=source[2]; destination +=3, source += 4; value++; } for (i=0;ibytes_userdata-(howmany*4)-begin;i++) destination[i]=source[i]; node->bytes_userdata -= howmany; tmp=node->data; node->data=node->newdata, node->newdata=tmp; return 0; } int DBH_Eunzip(DBHashTable *node,unsigned int begin,unsigned int howmany){ char *source,*destination; void *tmp; unsigned int i; if (!node) {WARNING8; return ERROR_VALUE;} if (node->bytes_userdata==0) {printf ("Bytes_userdata=0\n");return 1;} if (begin+howmany*3 > (unsigned int)(node->bytes_userdata)) {printf ("invalid parameters for Eunzip\n");return 1;} source=(char *)node->data, destination=(char *)node->newdata; for (i=0;ibytes_userdata-(howmany*3)-begin;i++) destination[i]=source[i]; node->bytes_userdata += howmany; tmp=node->data; node->data=node->newdata, node->newdata=tmp; return 0; } /* This function generates a key that belongs to a finite subset of the cuantified * numbers, but which preserves the order of the natural numbers (up to the supreme, * of course) */ void DBH_orderkey(unsigned char *numero, unsigned char orden,unsigned int n, unsigned char base) { int divisor,i,t; double d,b,o; if (!n) { printf("DBH_genkey: value must be > \n"); return; } for (i=0;i'Z') {t=numero[i]; t+=6; numero[i]=(unsigned char)t;}} } void DBH_exitsweep(DBHashTable *node) { if (!node) {WARNING8; return;} node->head_info->DBH_exit=1; } /* This function is not needed if DBH_set_data() is used to set * the record data. */ void DBH_set_recordsize(DBHashTable *node,int size){ if (!node) {WARNING8; return;} node->bytes_userdata=size; } /* This function is no longer needed with DBH_sweep(). It's main use is * for compatibility purposes with older programs */ void DBH_set_operate(DBHashTable *node,void (*operate)(struct DBHashTable *)){ if (!node) {WARNING8; return;} node->operate=operate; } /* Convenience function that does a close and rm */ DBHashTable * DBH_destroy(DBHashTable *node){ char file[256]; if (!node) {WARNING8; return NULL;} strcpy(file,node->head_info->archivo); DBH_close(node); if (remove(file)<0){ printf("\nCannot remove %s\n;",file); } return NULL; } void DBH_set_key(DBHashTable *node,char *key){ if (!node || !key) { printf("DBH: invalid parameter in DBH_set_key()\n"); return; } #ifdef HAVE_MEMCPY memcpy((void *)node->key,(void *)key,node->head_info->n_limit); #else { int i; char *t; t=node->key; for (i=0;ihead_info->n_limit;i++) { *t=key[i]; t++; } } #endif } void DBH_set_data(DBHashTable *node, void *data, int n){ if (!node || !data) { printf("DBH: invalid parameter in DBH_set_data()\n"); return; } if (n > node->head_info->record_length) { printf("DBH: redefining maximum record size to %d\n",n); DBH_Size(node,n); return; } #ifdef HAVE_MEMCPY memcpy((void *)node->data,(void *)data,n ); #else { int i; char *t,*s; s=(char *)data; t=(char *)node->data; for (i=0;ibytes_userdata=n; } /**************************************************************************/ static void mark_erased(DBHashTable *node){ SET_ERASED; /* set file pointer at record flag byte */ fseek(node->database,(node->head_info->reservedB)+1,SEEK_SET); /* write the flag to the file */ /* printf("flag for erase=0x%x\n",node->flag);*/ if (fwrite(&(node->flag),1,1,node->database) != 1) { printf("unable to erase %lu\n",(long unsigned)(node->head_info->reservedB+1)); return; } /*printf("erasing %s flag at %lu\n",(char *)node->data, (long unsigned)(node->head_info->reservedB+1));*/ /* update file header information */ node->head_info->data_space -= node->bytes_userdata; node->head_info->erased_space += (node->bytes_userdata); return; } int DBH_prune(DBHashTable *node,unsigned char *key,unsigned char subtree_length){ int result; node->head_info->sweep_erased=1; result=DBH_sweep(node,mark_erased,key,NULL,subtree_length); node->head_info->sweep_erased=0; /* update file header information */ DBH_writeheader(node); return result; } static void mark_unerased(DBHashTable *node){ SET_UNERASED; /* set file pointer at record flag byte */ fseek(node->database,(node->head_info->reservedB)+1,SEEK_SET); /* write the flag to the file */ if (fwrite(&(node->flag),1,1,node->database) != 1) { printf("unable to unerase %lu\n",(long unsigned)(node->head_info->reservedB+1)); return; } /* update file header information */ node->head_info->data_space += node->bytes_userdata; node->head_info->erased_space -= (node->bytes_userdata); return; } int DBH_unprune(DBHashTable *node,unsigned char *key,unsigned char subtree_length){ int result; node->head_info->sweep_erased=1; result=DBH_sweep(node,mark_unerased,key,NULL,subtree_length); node->head_info->sweep_erased=0; /* update file header information */ DBH_writeheader(node); return result; } /****************************************************************/