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

📄 hash_page.c

📁 asterisk 一个模拟IPPBX的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	sp = (u_int16_t *)bufp->page;	/* Check if we are dynamically determining the fill factor */	if (hashp->FFACTOR == DEF_FFACTOR) {		hashp->FFACTOR = sp[0] >> 1;		if (hashp->FFACTOR < MIN_FFACTOR)			hashp->FFACTOR = MIN_FFACTOR;	}	bufp->flags |= BUF_MOD;	ovfl_num = overflow_page(hashp);#ifdef DEBUG1	tmp1 = bufp->addr;	tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;#endif	if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))		return (NULL);	bufp->ovfl->flags |= BUF_MOD;#ifdef DEBUG1	(void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",	    tmp1, tmp2, bufp->ovfl->addr);#endif	ndx = sp[0];	/*	 * Since a pair is allocated on a page only if there's room to add	 * an overflow page, we know that the OVFL information will fit on	 * the page.	 */	sp[ndx + 4] = OFFSET(sp);	sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;	sp[ndx + 1] = ovfl_num;	sp[ndx + 2] = OVFLPAGE;	sp[0] = ndx + 2;#ifdef HASH_STATISTICS	hash_overflows++;#endif	return (bufp->ovfl);}/* * Returns: *	 0 indicates SUCCESS *	-1 indicates FAILURE */extern int__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)	HTAB *hashp;	char *p;	u_int32_t bucket;	int is_bucket, is_disk, is_bitmap;{	register int fd, page, size;	int rsize;	u_int16_t *bp;	fd = hashp->fp;	size = hashp->BSIZE;	if ((fd == -1) || !is_disk) {		PAGE_INIT(p);		return (0);	}	if (is_bucket)		page = BUCKET_TO_PAGE(bucket);	else		page = OADDR_TO_PAGE(bucket);	if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||	    ((rsize = read(fd, p, size)) == -1))		return (-1);	bp = (u_int16_t *)p;	if (!rsize)		bp[0] = 0;	/* We hit the EOF, so initialize a new page */	else		if (rsize != size) {			errno = EFTYPE;			return (-1);		}	if (!is_bitmap && !bp[0]) {		PAGE_INIT(p);	} else		if (hashp->LORDER != BYTE_ORDER) {			register int i, max;			if (is_bitmap) {				max = hashp->BSIZE >> 2; /* divide by 4 */				for (i = 0; i < max; i++)					M_32_SWAP(((int *)p)[i]);			} else {				M_16_SWAP(bp[0]);				max = bp[0] + 2;				for (i = 1; i <= max; i++)					M_16_SWAP(bp[i]);			}		}	return (0);}/* * Write page p to disk * * Returns: *	 0 ==> OK *	-1 ==>failure */extern int__put_page(hashp, p, bucket, is_bucket, is_bitmap)	HTAB *hashp;	char *p;	u_int32_t bucket;	int is_bucket, is_bitmap;{	register int fd, page, size;	int wsize;	size = hashp->BSIZE;	if ((hashp->fp == -1) && open_temp(hashp))		return (-1);	fd = hashp->fp;	if (hashp->LORDER != BYTE_ORDER) {		register int i;		register int max;		if (is_bitmap) {			max = hashp->BSIZE >> 2;	/* divide by 4 */			for (i = 0; i < max; i++)				M_32_SWAP(((int *)p)[i]);		} else {			max = ((u_int16_t *)p)[0] + 2;			for (i = 0; i <= max; i++)				M_16_SWAP(((u_int16_t *)p)[i]);		}	}	if (is_bucket)		page = BUCKET_TO_PAGE(bucket);	else		page = OADDR_TO_PAGE(bucket);	if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||	    ((wsize = write(fd, p, size)) == -1))		/* Errno is set */		return (-1);	if (wsize != size) {		errno = EFTYPE;		return (-1);	}	return (0);}#define BYTE_MASK	((1 << INT_BYTE_SHIFT) -1)/* * Initialize a new bitmap page.  Bitmap pages are left in memory * once they are read in. */extern int__ibitmap(hashp, pnum, nbits, ndx)	HTAB *hashp;	int pnum, nbits, ndx;{	u_int32_t *ip;	int clearbytes, clearints;	if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)		return (1);	hashp->nmaps++;	clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;	clearbytes = clearints << INT_TO_BYTE;	(void)memset((char *)ip, 0, clearbytes);	(void)memset(((char *)ip) + clearbytes, 0xFF,	    hashp->BSIZE - clearbytes);	ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);	SETBIT(ip, 0);	hashp->BITMAPS[ndx] = (u_int16_t)pnum;	hashp->mapp[ndx] = ip;	return (0);}static u_int32_tfirst_free(map)	u_int32_t map;{	register u_int32_t i, mask;	mask = 0x1;	for (i = 0; i < BITS_PER_MAP; i++) {		if (!(mask & map))			return (i);		mask = mask << 1;	}	return (i);}static u_int16_toverflow_page(hashp)	HTAB *hashp;{	register u_int32_t *freep = 0;	register int max_free, offset, splitnum;	u_int16_t addr;	int bit, first_page, free_bit, free_page, i, in_use_bits, j;#ifdef DEBUG2	int tmp1, tmp2;#endif	splitnum = hashp->OVFL_POINT;	max_free = hashp->SPARES[splitnum];	free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);	free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);	/* Look through all the free maps to find the first free block */	first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);	for ( i = first_page; i <= free_page; i++ ) {		if (!(freep = (u_int32_t *)hashp->mapp[i]) &&		    !(freep = fetch_bitmap(hashp, i)))			return (0);		if (i == free_page)			in_use_bits = free_bit;		else			in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;				if (i == first_page) {			bit = hashp->LAST_FREED &			    ((hashp->BSIZE << BYTE_SHIFT) - 1);			j = bit / BITS_PER_MAP;			bit = bit & ~(BITS_PER_MAP - 1);		} else {			bit = 0;			j = 0;		}		for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)			if (freep[j] != ALL_SET)				goto found;	}	/* No Free Page Found */	hashp->LAST_FREED = hashp->SPARES[splitnum];	hashp->SPARES[splitnum]++;	offset = hashp->SPARES[splitnum] -	    (splitnum ? hashp->SPARES[splitnum - 1] : 0);#define	OVMSG	"HASH: Out of overflow pages.  Increase page size\n"	if (offset > SPLITMASK) {		if (++splitnum >= NCACHED) {			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);			return (0);		}		hashp->OVFL_POINT = splitnum;		hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];		hashp->SPARES[splitnum-1]--;		offset = 1;	}	/* Check if we need to allocate a new bitmap page */	if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {		free_page++;		if (free_page >= NCACHED) {			(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);			return (0);		}		/*		 * This is tricky.  The 1 indicates that you want the new page		 * allocated with 1 clear bit.  Actually, you are going to		 * allocate 2 pages from this map.  The first is going to be		 * the map page, the second is the overflow page we were		 * looking for.  The init_bitmap routine automatically, sets		 * the first bit of itself to indicate that the bitmap itself		 * is in use.  We would explicitly set the second bit, but		 * don't have to if we tell init_bitmap not to leave it clear		 * in the first place.		 */		if (__ibitmap(hashp,		    (int)OADDR_OF(splitnum, offset), 1, free_page))			return (0);		hashp->SPARES[splitnum]++;#ifdef DEBUG2		free_bit = 2;#endif		offset++;		if (offset > SPLITMASK) {			if (++splitnum >= NCACHED) {				(void)write(STDERR_FILENO, OVMSG,				    sizeof(OVMSG) - 1);				return (0);			}			hashp->OVFL_POINT = splitnum;			hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];			hashp->SPARES[splitnum-1]--;			offset = 0;		}	} else {		/*		 * Free_bit addresses the last used bit.  Bump it to address		 * the first available bit.		 */		free_bit++;		SETBIT(freep, free_bit);	}	/* Calculate address of the new overflow page */	addr = OADDR_OF(splitnum, offset);#ifdef DEBUG2	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",	    addr, free_bit, free_page);#endif	return (addr);found:	bit = bit + first_free(freep[j]);	SETBIT(freep, bit);#ifdef DEBUG2	tmp1 = bit;	tmp2 = i;#endif	/*	 * Bits are addressed starting with 0, but overflow pages are addressed	 * beginning at 1. Bit is a bit addressnumber, so we need to increment	 * it to convert it to a page number.	 */	bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));	if (bit >= hashp->LAST_FREED)		hashp->LAST_FREED = bit - 1;	/* Calculate the split number for this page */	for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);	offset = (i ? bit - hashp->SPARES[i - 1] : bit);	if (offset >= SPLITMASK)		return (0);	/* Out of overflow pages */	addr = OADDR_OF(i, offset);#ifdef DEBUG2	(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",	    addr, tmp1, tmp2);#endif	/* Allocate and return the overflow page */	return (addr);}/* * Mark this overflow page as free. */extern void__free_ovflpage(hashp, obufp)	HTAB *hashp;	BUFHEAD *obufp;{	register u_int16_t addr;	u_int32_t *freep;	int bit_address, free_page, free_bit;	u_int16_t ndx;	addr = obufp->addr;#ifdef DEBUG1	(void)fprintf(stderr, "Freeing %d\n", addr);#endif	ndx = (((u_int16_t)addr) >> SPLITSHIFT);	bit_address =	    (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;	 if (bit_address < hashp->LAST_FREED)		hashp->LAST_FREED = bit_address;	free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));	free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);	if (!(freep = hashp->mapp[free_page]))		freep = fetch_bitmap(hashp, free_page);#ifdef DEBUG	/*	 * This had better never happen.  It means we tried to read a bitmap	 * that has already had overflow pages allocated off it, and we	 * failed to read it from the file.	 */	if (!freep)		assert(0);#endif	CLRBIT(freep, free_bit);#ifdef DEBUG2	(void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",	    obufp->addr, free_bit, free_page);#endif	__reclaim_buf(hashp, obufp);}/* * Returns: *	 0 success *	-1 failure */static intopen_temp(hashp)	HTAB *hashp;{	sigset_t set, oset;	static char namestr[] = "_hashXXXXXX";	/* Block signals; make sure file goes away at process exit. */	(void)sigfillset(&set);	(void)sigprocmask(SIG_BLOCK, &set, &oset);	if ((hashp->fp = mkstemp(namestr)) != -1) {		(void)unlink(namestr);		(void)fcntl(hashp->fp, F_SETFD, 1);	}	(void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);	return (hashp->fp != -1 ? 0 : -1);}/* * We have to know that the key will fit, but the last entry on the page is * an overflow pair, so we need to shift things. */static voidsqueeze_key(sp, key, val)	u_int16_t *sp;	const DBT *key, *val;{	register char *p;	u_int16_t free_space, n, off, pageno;	p = (char *)sp;	n = sp[0];	free_space = FREESPACE(sp);	off = OFFSET(sp);	pageno = sp[n - 1];	off -= key->size;	sp[n - 1] = off;	memmove(p + off, key->data, key->size);	off -= val->size;	sp[n] = off;	memmove(p + off, val->data, val->size);	sp[0] = n + 2;	sp[n + 1] = pageno;	sp[n + 2] = OVFLPAGE;	FREESPACE(sp) = free_space - PAIRSIZE(key, val);	OFFSET(sp) = off;}static u_int32_t *fetch_bitmap(hashp, ndx)	HTAB *hashp;	int ndx;{	if (ndx >= hashp->nmaps)		return (NULL);	if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)		return (NULL);	if (__get_page(hashp,	    (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {		free(hashp->mapp[ndx]);		return (NULL);	}	return (hashp->mapp[ndx]);}#ifdef DEBUG4intprint_chain(addr)	int addr;{	BUFHEAD *bufp;	short *bp, oaddr;	(void)fprintf(stderr, "%d ", addr);	bufp = __get_buf(hashp, addr, NULL, 0);	bp = (short *)bufp->page;	while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||		((bp[0] > 2) && bp[2] < REAL_KEY))) {		oaddr = bp[bp[0] - 1];		(void)fprintf(stderr, "%d ", (int)oaddr);		bufp = __get_buf(hashp, (int)oaddr, bufp, 0);		bp = (short *)bufp->page;	}	(void)fprintf(stderr, "\n");}#endif

⌨️ 快捷键说明

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