#include <stdio.h> #include <unistd.h> #include "copyright.h" #include "config.h" #include "db.h" #include "externs.h" #include "params.h" #include "lru.h" #ifdef USE_DBP #define BUFFER_LEN 1024 #define FREE_IT 1 #define SAVE_IT 0 #define END_MOVE "***Property list end ***" /* 24 */ #define BEGIN_MOVE "***Property list start ***" /* 26 */ #define MAXOBJS 256 #define FUDGE_FACTOR 32 #define PEROBJECT_FUDGE 55 #define PERLINE_FUDGE 3 /* change this variable on the fly to resize cache. */ /* make it < 1 and you are doomed. */ /* be afraid. be very afraid */ int dbp_max_objects = MAXOBJS; static int enable = 0; static int lock = 0; static FILE *map, *data; /* calculate the disk space needed to store the property entries for a single object. There's probably a more elegant solution, but this one is sure to work. */ static int calclen = 0; static int totallen = 0; static int digitsin(int x) { int y = 1; while (x /= 10) y++; return y; } /* old one, it's buggy... I'll buy you a pizza if you can tell me why -- Doran static void calc_putprop_recurse(propdir *p) { int end; for (; p; p = p->next) { if (p->child) { end = calclen; calclen += strlen(p->name) + 1; calc_putprop_recurse(p->child); calclen = end; } if (p->data) { totallen += calclen + strlen(p->name) + digitsin(p->perms) + strlen(p->data) + PERLINE_FUDGE; } } } */ /* if this one doesn't work I'll hang it up right now. */ char buf[BUFFER_LEN * 16]; char buf2[BUFFER_LEN * 16]; void calc_putprop_recurse(propdir *p) { char *end; for (; p; p = p->next) { if (p->child) { end = buf2 + strlen(buf2); strcat(buf2, p->name); strcat(buf2, "/"); calc_putprop_recurse(p->child); *end = '\0'; } if (p->data) { sprintf (buf, "%s%s:%d:%s\n", buf2, p->name, p->perms, p->data); /* fputs(buf, f); */ totallen += strlen(buf); } } } static int calc_putprop(dbref obj) { calclen = totallen = 0; calc_putprop_recurse(DBFETCHPROP(obj)); return (totallen + PEROBJECT_FUDGE + digitsin(obj)); } void dbp_lock(void) { lock++; } void dbp_unlock(void) { lock--; } int dbp_enable(char *name) { char fname[BUFFER_LEN]; sprintf(fname, "%s.map", name); map = fopen(fname, "r+"); if (map == NULL) { fprintf(stderr, "Trouble opening map file %s.\n", fname); return 1; } sprintf(fname, "%s.dat", name); data = fopen(fname, "r+"); if (data == NULL) { fprintf(stderr, "Trouble opening data file %s.\n", fname); return 1; } enable = 1; return 0; } void dbp_disable(void) { if (enable != 1) return; fclose(map); fclose(data); enable = 0; } static void dbp_unload(long what, int freeflag) { long tmp[2]; int size; long start, end; if (enable == 0) return; if (lock > 0) return; lock++; size = calc_putprop(what); if (size <= DBFETCH(what)->dbp_size) { fseek(map, sizeof(long) * 2 * (what + 1), SEEK_SET); fread(tmp, sizeof(long), 2, map); fseek(data, tmp[1], SEEK_SET); } else { fseek(data, 0L, SEEK_END); /* we're bigger now, remember that */ DBSTORE(what, dbp_size, size); } if(DBFETCH(what)->properties) { tmp[0] = what; tmp[1] = ftell(data); } else { tmp[0] = -1L; tmp[1] = -1L; DBSTORE(what, dbp_size, -1L); /* free me do me */ } fseek(map, sizeof(long) * 2 * (what + 1), SEEK_SET); fwrite(tmp, sizeof(long), 2, map); fflush(map); if (DBFETCH(what)->properties) { start = ftell(data); fprintf(data, "%s - %ld\n", BEGIN_MOVE, what); putproperties(data, what); fprintf(data, "%s\n", END_MOVE); fflush(data); end = ftell(data); if ((end - start) != size) { /* oh shit, we've got a boo boo, spew errors like */ /* a sunovabitch and exit (we're hopelessly */ /* screwed by this point) */ fprintf(stderr, "DBP: Fatal Error!\n"); fprintf(stderr, " : %ld -> %d/%d\n", what, (end - start), size); fprintf(stderr, "%s - %ld\n", BEGIN_MOVE, what); putproperties(stderr, what); fprintf(stderr, "%s\n", END_MOVE); exit(0xbabe); } if (freeflag == FREE_IT) { burn_proptree(DBFETCH(what)->properties); DBFETCH(what)->properties = NULL; } } lock--; } void dbp_load(long what) { long offset[2]; if (enable == 0) return; if (lock > 0) return; lock++; if (lru_hasp(what) == 1) { lock--; return; } if (DBFETCH(what)->properties != NULL) { lock--; lru_use(what); return; } lru_use(what); offset[0] = sizeof(long) * 2 * (what + 1); fseek(map, offset[0], SEEK_SET); fread(offset, sizeof(long), 2, map); if (offset[0] == -1L || offset[1] == -1L) { offset[0] = -1L; offset[1] = -1L; fseek(map, sizeof(long) * 2 * (what + 1), SEEK_SET); fwrite(offset, sizeof(long), 2, map); fflush(map); DBSTORE(what, dbp_size, -1); } else if (offset[0] == what) { fseek(data, offset[1], SEEK_SET); getproperties(data, what, 1); /* check me do me */ if (DBFETCH(what)->dbp_size == -1L) DBSTORE(what, dbp_size, calc_putprop(what)); } while (lru_count() > dbp_max_objects) dbp_unload(lru_old(), FREE_IT); lock--; } void dbp_flush(void) { if (enable == 0) return; while (lru_count() > 0) dbp_unload(lru_old(), FREE_IT); } void dbp_sync(void) { dbref spot; if (enable == 0) return; for (spot = lru_head(); spot != NOTHING; spot = DBFETCH(spot)->lru_next) { dbp_unload(spot, SAVE_IT); } } void dbstoreprop(long what, propdir *p) { dbp_load(what); DBSTORE(what, properties, p); } propdir *dbfetchprop(long what) { dbp_load(what); return (DBFETCH(what)->properties); } #endif