⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbz.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
		return(-1);	f = fopen(fn, "w");	free((POINTER)fn);	if (f == NULL) {		DEBUG(("dbzfresh: unable to create/truncate .pag file\n"));		return(-1);	} else		(void) fclose(f);	/* and punt to dbminit for the hard work */	return(dbminit(name));}/* - dbzsize - what's a good table size to hold this many entries? */longdbzsize(contents)long contents;			/* 0 means what's the default */{	register long n;	if (contents <= 0) {	/* foulup or default inquiry */		DEBUG(("dbzsize: preposterous input (%ld)\n", contents));		return(DEFSIZE);	}	n = (contents/2)*3;	/* try to keep table at most 2/3 full */	if (!(n&01))		/* make it odd */		n++;	DEBUG(("dbzsize: tentative size %ld\n", n));	while (!isprime(n))	/* and look for a prime */		n += 2;	DEBUG(("dbzsize: final size %ld\n", n));	return(n);}/* - isprime - is a number prime? * * This is not a terribly efficient approach. */static int			/* predicate */isprime(x)register long x;{	static int quick[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 0 };	register int *ip;	register long div;	register long stop;	/* hit the first few primes quickly to eliminate easy ones */	/* this incidentally prevents ridiculously small tables */	for (ip = quick; (div = *ip) != 0; ip++)		if (x%div == 0) {			DEBUG(("isprime: quick result on %ld\n", (long)x));			return(0);		}	/* approximate square root of x */	for (stop = x; x/stop < stop; stop >>= 1)		continue;	stop <<= 1;	/* try odd numbers up to stop */	for (div = *--ip; div < stop; div += 2)		if (x%div == 0)			return(0);	return(1);}/* - dbzagain - set up a new database to be a rebuild of an old one */int				/* 0 success, -1 failure */dbzagain(name, oldname)char *name;			/* base name; .dir and .pag must exist */char *oldname;			/* base name; all must exist */{	register char *fn;	struct dbzconfig c;	register int i;	register long top;	register FILE *f;	register int newtable;	register of_t newsize;	struct stat sb;	register of_t m;	if (pagf != NULL) {		DEBUG(("dbzagain: database already open\n"));		return(-1);	}	/* pick up the old configuration */	fn = enstring(oldname, dir);	if (fn == NULL)		return(-1);	f = fopen(fn, "r");	free((POINTER)fn);	if (f == NULL) {		DEBUG(("dbzagain: cannot open old .dir file\n"));		return(-1);	}	i = getconf(f, (FILE *)NULL, &c);	(void) fclose(f);	if (i < 0) {		DEBUG(("dbzagain: getconf failed\n"));		return(-1);	}	/* calculate tagging from old file */	if (stat(oldname, &sb) != -1) {		 for (m = 1, i = 0; m < sb.st_size; i++, m <<= 1)			 continue;		 		 /* if we had more tags than the default, use the new data */		 if ((c.tagmask | c.tagenb) && m > (1 << TAGSHIFT)) {			  c.tagshift = i;			  c.tagmask = (~(unsigned long)0) >> (i + 1);			  c.tagenb = (c.tagmask << 1) & ~c.tagmask;		 }	}	/* tinker with it */	top = 0;	newtable = 0;	for (i = 0; i < NUSEDS; i++) {		if (top < c.used[i])			top = c.used[i];		if (c.used[i] == 0)			newtable = 1;	/* hasn't got full usage history yet */	}	if (top == 0) {		DEBUG(("dbzagain: old table has no contents!\n"));		newtable = 1;	}	for (i = NUSEDS-1; i > 0; i--)		c.used[i] = c.used[i-1];	c.used[0] = 0;	newsize = dbzsize(top);	if (!newtable || newsize > c.tsize)	/* don't shrink new table */		c.tsize = newsize;	/* write it out */	fn = enstring(name, dir);	if (fn == NULL)		return(-1);	f = fopen(fn, "w");	free((POINTER)fn);	if (f == NULL) {		DEBUG(("dbzagain: unable to write new .dir\n"));		return(-1);	}	i = putconf(f, &c);	(void) fclose(f);	if (i < 0) {		DEBUG(("dbzagain: putconf failed\n"));		return(-1);	}	/* create/truncate .pag */	fn = enstring(name, pag);	if (fn == NULL)		return(-1);	f = fopen(fn, "w");	free((POINTER)fn);	if (f == NULL) {		DEBUG(("dbzagain: unable to create/truncate .pag file\n"));		return(-1);	} else		(void) fclose(f);	/* and let dbminit do the work */	return(dbminit(name));}/* - dbminit - open a database, creating it (using defaults) if necessary * * We try to leave errno set plausibly, to the extent that underlying * functions permit this, since many people consult it if dbminit() fails. */int 				/* 0 success, -1 failure */dbminit(name)char *name;{	register int i;	register size_t s;	register char *dirfname;	register char *pagfname;	if (pagf != NULL) {		DEBUG(("dbminit: dbminit already called once\n"));		errno = 0;		return(-1);	}	/* open the .dir file */	dirfname = enstring(name, dir);	if (dirfname == NULL)		return(-1);	dirf = fopen(dirfname, "r+");	if (dirf == NULL) {		dirf = fopen(dirfname, "r");		dirronly = 1;	} else		dirronly = 0;	free((POINTER)dirfname);	if (dirf == NULL) {		DEBUG(("dbminit: can't open .dir file\n"));		return(-1);	}	CloseOnExec((int)fileno(dirf), 1);	/* open the .pag file */	pagfname = enstring(name, pag);	if (pagfname == NULL) {		(void) fclose(dirf);		return(-1);	}	pagf = fopen(pagfname, "r+b");	if (pagf == NULL) {		pagf = fopen(pagfname, "rb");		if (pagf == NULL) {			DEBUG(("dbminit: .pag open failed\n"));			(void) fclose(dirf);			free((POINTER)pagfname);			return(-1);		}		pagronly = 1;	} else if (dirronly)		pagronly = 1;	else		pagronly = 0;	if (pagf != NULL)		CloseOnExec((int)fileno(pagf), 1);#ifdef NOBUFFER	/*	 * B News does not do adequate locking on its database accesses.	 * Why it doesn't get into trouble using dbm is a mystery.  In any	 * case, doing unbuffered i/o does not cure the problem, but does	 * enormously reduce its incidence.	 */	(void) setbuf(pagf, (char *)NULL);#else#ifdef _IOFBF	(void) setvbuf(pagf, (char *)pagbuf, _IOFBF, sizeof(pagbuf));#endif#endif	pagpos = -1;	/* don't free pagfname, need it below */	/* open the base file */	basef = fopen(name, "r");	if (basef == NULL) {		DEBUG(("dbminit: basefile open failed\n"));		basefname = enstring(name, "");		if (basefname == NULL) {			(void) fclose(pagf);			(void) fclose(dirf);			free((POINTER)pagfname);			pagf = NULL;			return(-1);		}	} else		basefname = NULL;	if (basef != NULL)		CloseOnExec((int)fileno(basef), 1);#ifdef _IOFBF	if (basef != NULL)		(void) setvbuf(basef, basebuf, _IOFBF, sizeof(basebuf));#endif	/* pick up configuration */	if (getconf(dirf, pagf, &conf) < 0) {		DEBUG(("dbminit: getconf failure\n"));		(void) fclose(basef);		(void) fclose(pagf);		(void) fclose(dirf);		free((POINTER)pagfname);		pagf = NULL;		errno = EDOM;	/* kind of a kludge, but very portable */		return(-1);	}	tagbits = conf.tagmask << conf.tagshift;	taghere = conf.tagenb << conf.tagshift;	tagboth = tagbits | taghere;	mybytemap(mybmap);	bytesame = 1;	for (i = 0; i < SOF; i++)		if (mybmap[i] != conf.bytemap[i])			bytesame = 0;	/* get first table into core, if it looks desirable and feasible */	s = (size_t)conf.tsize * SOF;	if (incore && (of_t)(s/SOF) == conf.tsize) {		bufpagf = fopen(pagfname, (pagronly) ? "rb" : "r+b");		if (bufpagf != NULL) {			corepag = getcore(bufpagf);			CloseOnExec((int)fileno(bufpagf), 1);		}	} else {		bufpagf = NULL;		corepag = NULL;	}	free((POINTER)pagfname);	/* misc. setup */	crcinit();	written = 0;	prevp = FRESH;	DEBUG(("dbminit: succeeded\n"));	return(0);}/* - enstring - concatenate two strings into a malloced area */static char *			/* NULL if malloc fails */enstring(s1, s2)char *s1;char *s2;{	register char *p;	p = malloc((size_t)strlen(s1) + (size_t)strlen(s2) + 1);	if (p != NULL) {		(void) strcpy(p, s1);		(void) strcat(p, s2);	} else {		DEBUG(("enstring(%s, %s) out of memory\n", s1, s2));	}	return(p);}/* - dbmclose - close a database */intdbmclose(){	register int ret = 0;	if (pagf == NULL) {		DEBUG(("dbmclose: not opened!\n"));		return(-1);	}	if (fclose(pagf) == EOF) {		DEBUG(("dbmclose: fclose(pagf) failed\n"));		ret = -1;	}	pagf = basef;		/* ensure valid pointer; dbzsync checks it */	if (dbzsync() < 0)		ret = -1;	if (bufpagf != NULL && fclose(bufpagf) == EOF) {		DEBUG(("dbmclose: fclose(bufpagf) failed\n"));		ret = -1;	}	if (corepag != NULL)#ifdef MMAP		if (munmap(corepag, (int)conf.tsize * SOF) == -1) {			DEBUG(("dbmclose: munmap failed\n"));			ret = -1;		}#else		free((POINTER)corepag);#endif	corepag = NULL;	if (fclose(basef) == EOF) {		DEBUG(("dbmclose: fclose(basef) failed\n"));		ret = -1;	}	if (basefname != NULL)		free((POINTER)basefname);	basef = NULL;	pagf = NULL;	if (fclose(dirf) == EOF) {		DEBUG(("dbmclose: fclose(dirf) failed\n"));		ret = -1;	}	DEBUG(("dbmclose: %s\n", (ret == 0) ? "succeeded" : "failed"));	return(ret);}/* - dbzsync - push all in-core data out to disk */intdbzsync(){	register int ret = 0;	if (pagf == NULL) {		DEBUG(("dbzsync: not opened!\n"));		return(-1);	}	if (!written)		return(0);#ifndef MMAP	if (corepag != NULL && !writethrough) {		if (putcore(corepag, bufpagf) < 0) {			DEBUG(("dbzsync: putcore failed\n"));			ret = -1;		}	}#endif	if (!conf.olddbz)		if (putconf(dirf, &conf) < 0)			ret = -1;	DEBUG(("dbzsync: %s\n", (ret == 0) ? "succeeded" : "failed"));	return(ret);}/* - dbzcancel - cancel writing of in-core data * Mostly for use from child processes. * Note that we don't need to futz around with stdio buffers, because we * always fflush them immediately anyway and so they never have stale data. */intdbzcancel(){	if (pagf == NULL) {		DEBUG(("dbzcancel: not opened!\n"));		return(-1);	}	written = 0;	return(0);}/* - dbzfetch - fetch() with case mapping built in */datumdbzfetch(key)datum key;{	char buffer[DBZMAXKEY + 1];	datum mappedkey;	register size_t keysize;	DEBUG(("dbzfetch: (%s)\n", key.dptr));	/* Key is supposed to be less than DBZMAXKEY */	keysize = key.dsize;	if (keysize >= DBZMAXKEY) {		keysize = DBZMAXKEY;		DEBUG(("keysize is %d - truncated to %d\n", key.dsize, DBZMAXKEY));	}	mappedkey.dptr = mapcase(buffer, key.dptr, keysize);	buffer[keysize] = '\0';	/* just a debug aid */	mappedkey.dsize = keysize;	return(fetch(mappedkey));}/* - fetch - get an entry from the database * * Disgusting fine point, in the name of backward compatibility:  if the * last character of "key" is a NUL, that character is (effectively) not * part of the comparison against the stored keys. */datum				/* dptr NULL, dsize 0 means failure */fetch(key)datum key;{	char buffer[DBZMAXKEY + 1];	static of_t key_ptr;		/* return value points here */	datum output;	register size_t keysize;	register size_t cmplen;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -