/* A Berkeley dynahash compatible interface for the UnterMud database layer as slightly whacked by Andrew Molitor. NOTE: This code assumes that keys are all \0 terminated strings. If they are not, all hell will break loose and you will rapidly get many fine core dumps. So, always fill in your key DBTs with 'data' pointing at a \0 terminated string, and size strlen() of that string. Always. */ /* FIRST */ #include "udb_defs.h" #include <stdio.h> #ifdef NOSYSTYPES_H #include <types.h> #else #include <sys/types.h> #endif #include "udb.h" static int dyna_close(); static int dyna_delete(); static int dyna_get(); static int dyna_put(); static int dyna_seq(); static int dyna_sync(); extern void tmp_sync(); extern void deferfree(); /* Open a database. Named this because the dynahash thang is. We totally ignore most of the parameters. Everything except the file name, actually. */ extern DB * hash_open(file, flags, mode, info) const char *file; int flags; int mode; const HASHINFO *info; /* Special directives for create */ { DB *dbp; cache_init(); dddb_setfile(file); /* Set up the name */ DB_INIT(); /* Start that mother up */ /* Get a DB struct */ if((dbp = (DB *)malloc(sizeof(DB))) == (DB *)0){ return ((DB *)0); } /* Fill it in */ dbp->close = dyna_close; dbp->del = dyna_delete; dbp->get = dyna_get; dbp->put = dyna_put; dbp->seq = dyna_seq; dbp->sync = dyna_sync; return(dbp); } /* Internal DB access gear. All these do is translate for the untermud DB layer. */ static int dyna_close(dbp) DB *dbp; /* Unused. */ { tmp_sync(); /* Sync out the temp memory allocator..*/ cache_sync(); /* .. and the cache */ DB_CLOSE(); /* Close it up. */ return 0; } static int dyna_delete(dbp,key,flags) DB *dbp; /* Unused. */ DBT *key; u_long flags; /* Unused. */ { if(cache_del(key->data,key->size,0)){ return(-1); } return(0); } static int dyna_get(dbp,key,data,flags) DB *dbp; /* Unused. */ DBT *key; DBT *data; u_long flags; /* Unused. */ { Attr *a; if((a = cache_get(key->data, key->size)) == (Attr *)0){ return(-1); } data->size = a->size; data->data = a->data; return(0); } static int dyna_put(dbp,key,data,flag) DB *dbp; /* Unused. */ DBT *key; DBT *data; u_long flag; /* Unused. */ { Attr *a; char *p; int existed = 1; /* This is complicated. If the attribute exists, we need a pointer to the in-cache Attr. */ a = cache_get(key->data, key->size); if(a == (Attr *)0){ /* New thing, looks like */ a = (Attr *)malloc(sizeof(Attr)); if(a == (Attr *)0){ return(-1); } existed = 0; } p = (char *)malloc(data->size); if(p == (char *)0){ return(-1); } bcopy(data->data,p,data->size); if(existed) /* free(a->data); */ deferfree(a->data); a->data = p; a->size = data->size; /* Now stick it into the cache */ if(cache_put(a,key->data, key->size)) return(-1); return(0); } /* This is slightly sticky. It walks the *disk* copy of the database, syncing the cache when you go get the first key. So going in and fucking with the database while traversing it is probably *real* dumb. */ static int dyna_seq(dbp,key,data,flag) DB *dbp; /* Unused. */ DBT *key; DBT *data; u_long flag; { static char currkey[MAXKEY+1]; /* For luck */ Attr *a; if(flag == R_FIRST){ /* Sync out the cache, first */ cache_sync(); DB_TRAVSTART(); } if(DB_TRAVERSE(currkey) == 0) return(-1); if((a = cache_get(currkey, strlen(currkey)+1)) == (Attr *)0) return(-1); key->size = strlen(currkey); key->data = currkey; data->size = a->size; data->data = a->data; return(0); } /* Write modified data to disk. Return -1 on fail, 0 success. */ static int dyna_sync(dbp) DB *dbp; /* Unused. */ { /* This is probably a good time to do these two, as well. */ tmp_sync(); cache_reset(); if(cache_sync()) return(-1); return(0); }