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

📄 hash_bigkey.c

📁 asterisk 一个模拟IPPBX的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1990, 1993, 1994 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Margo Seltzer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#if defined(LIBC_SCCS) && !defined(lint)static char sccsid[] = "@(#)hash_bigkey.c	8.3 (Berkeley) 5/31/94";#endif /* LIBC_SCCS and not lint *//* * PACKAGE: hash * DESCRIPTION: *	Big key/data handling for the hashing package. * * ROUTINES: * External *	__big_keydata *	__big_split *	__big_insert *	__big_return *	__big_delete *	__find_last_page * Internal *	collect_key *	collect_data */#include <sys/param.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef DEBUG#include <assert.h>#endif#include "../include/db.h"#include "hash.h"#include "page.h"#include "extern.h"static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int));static int collect_data __P((HTAB *, BUFHEAD *, int, int));/* * Big_insert * * You need to do an insert and the key/data pair is too big * * Returns: * 0 ==> OK *-1 ==> ERROR */extern int__big_insert(hashp, bufp, key, val)	HTAB *hashp;	BUFHEAD *bufp;	const DBT *key, *val;{	register u_int16_t *p;	int key_size, n, val_size;	u_int16_t space, move_bytes, off;	char *cp, *key_data, *val_data;	cp = bufp->page;		/* Character pointer of p. */	p = (u_int16_t *)cp;	key_data = (char *)key->data;	key_size = key->size;	val_data = (char *)val->data;	val_size = val->size;	/* First move the Key */	for (space = FREESPACE(p) - BIGOVERHEAD; key_size;	    space = FREESPACE(p) - BIGOVERHEAD) {		move_bytes = MIN(space, key_size);		off = OFFSET(p) - move_bytes;		memmove(cp + off, key_data, move_bytes);		key_size -= move_bytes;		key_data += move_bytes;		n = p[0];		p[++n] = off;		p[0] = ++n;		FREESPACE(p) = off - PAGE_META(n);		OFFSET(p) = off;		p[n] = PARTIAL_KEY;		bufp = __add_ovflpage(hashp, bufp);		if (!bufp)			return (-1);		n = p[0];		if (!key_size) {			if (FREESPACE(p)) {				move_bytes = MIN(FREESPACE(p), val_size);				off = OFFSET(p) - move_bytes;				p[n] = off;				memmove(cp + off, val_data, move_bytes);				val_data += move_bytes;				val_size -= move_bytes;				p[n - 2] = FULL_KEY_DATA;				FREESPACE(p) = FREESPACE(p) - move_bytes;				OFFSET(p) = off;			} else				p[n - 2] = FULL_KEY;		}		p = (u_int16_t *)bufp->page;		cp = bufp->page;		bufp->flags |= BUF_MOD;	}	/* Now move the data */	for (space = FREESPACE(p) - BIGOVERHEAD; val_size;	    space = FREESPACE(p) - BIGOVERHEAD) {		move_bytes = MIN(space, val_size);		/*		 * Here's the hack to make sure that if the data ends on the		 * same page as the key ends, FREESPACE is at least one.		 */		if ((int) space == val_size && (size_t) val_size == val->size)			move_bytes--;		off = OFFSET(p) - move_bytes;		memmove(cp + off, val_data, move_bytes);		val_size -= move_bytes;		val_data += move_bytes;		n = p[0];		p[++n] = off;		p[0] = ++n;		FREESPACE(p) = off - PAGE_META(n);		OFFSET(p) = off;		if (val_size) {			p[n] = FULL_KEY;			bufp = __add_ovflpage(hashp, bufp);			if (!bufp)				return (-1);			cp = bufp->page;			p = (u_int16_t *)cp;		} else			p[n] = FULL_KEY_DATA;		bufp->flags |= BUF_MOD;	}	return (0);}/* * Called when bufp's page  contains a partial key (index should be 1) * * All pages in the big key/data pair except bufp are freed.  We cannot * free bufp because the page pointing to it is lost and we can't get rid * of its pointer. * * Returns: * 0 => OK *-1 => ERROR */extern int__big_delete(hashp, bufp)	HTAB *hashp;	BUFHEAD *bufp;{	register BUFHEAD *last_bfp, *rbufp;	u_int16_t *bp, pageno;	int key_done, n;	rbufp = bufp;	last_bfp = NULL;	bp = (u_int16_t *)bufp->page;	pageno = 0;	key_done = 0;	while (!key_done || (bp[2] != FULL_KEY_DATA)) {		if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)			key_done = 1;		/*		 * If there is freespace left on a FULL_KEY_DATA page, then		 * the data is short and fits entirely on this page, and this		 * is the last page.		 */		if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))			break;		pageno = bp[bp[0] - 1];		rbufp->flags |= BUF_MOD;		rbufp = __get_buf(hashp, pageno, rbufp, 0);		if (last_bfp)			__free_ovflpage(hashp, last_bfp);		last_bfp = rbufp;		if (!rbufp)			return (-1);		/* Error. */		bp = (u_int16_t *)rbufp->page;	}	/*	 * If we get here then rbufp points to the last page of the big	 * key/data pair.  Bufp points to the first one -- it should now be	 * empty pointing to the next page after this pair.  Can't free it	 * because we don't have the page pointing to it.	 */	/* This is information from the last page of the pair. */	n = bp[0];	pageno = bp[n - 1];	/* Now, bp is the first page of the pair. */	bp = (u_int16_t *)bufp->page;	if (n > 2) {		/* There is an overflow page. */		bp[1] = pageno;		bp[2] = OVFLPAGE;		bufp->ovfl = rbufp->ovfl;	} else		/* This is the last page. */		bufp->ovfl = NULL;	n -= 2;	bp[0] = n;	FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);	OFFSET(bp) = hashp->BSIZE - 1;	bufp->flags |= BUF_MOD;	if (rbufp)		__free_ovflpage(hashp, rbufp);	if (last_bfp && last_bfp != rbufp)		__free_ovflpage(hashp, last_bfp);	hashp->NKEYS--;	return (0);}/* * Returns: *  0 = key not found * -1 = get next overflow page * -2 means key not found and this is big key/data * -3 error */extern int__find_bigpair(hashp, bufp, ndx, key, size)	HTAB *hashp;	BUFHEAD *bufp;	int ndx;	char *key;	int size;{	register u_int16_t *bp;	register char *p;	int ksize;	u_int16_t bytes;	char *kkey;	bp = (u_int16_t *)bufp->page;	p = bufp->page;	ksize = size;	kkey = key;	for (bytes = hashp->BSIZE - bp[ndx];	    bytes <= size && bp[ndx + 1] == PARTIAL_KEY;	    bytes = hashp->BSIZE - bp[ndx]) {		if (memcmp(p + bp[ndx], kkey, bytes))			return (-2);		kkey += bytes;		ksize -= bytes;		bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);		if (!bufp)			return (-3);		p = bufp->page;		bp = (u_int16_t *)p;		ndx = 1;	}	if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {#ifdef HASH_STATISTICS		++hash_collisions;#endif		return (-2);	} else		return (ndx);}/* * Given the buffer pointer of the first overflow page of a big pair, * find the end of the big pair * * This will set bpp to the buffer header of the last page of the big pair. * It will return the pageno of the overflow page following the last page * of the pair; 0 if there isn't any (i.e. big pair is the last key in the * bucket) */extern u_int16_t__find_last_page(hashp, bpp)	HTAB *hashp;	BUFHEAD **bpp;{	BUFHEAD *bufp;	u_int16_t *bp, pageno;	int n;	bufp = *bpp;	bp = (u_int16_t *)bufp->page;	for (;;) {		n = bp[0];		/*		 * This is the last page if: the tag is FULL_KEY_DATA and		 * either only 2 entries OVFLPAGE marker is explicit there		 * is freespace on the page.

⌨️ 快捷键说明

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