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

📄 cache.c

📁 RADIUS协议的认证计费服务
💻 C
字号:
/* * ASCEND: @(#)cache.c	1.0 (95/10/05 00:55:30) * *      Copyright (c) 1994 Ascend Communications, Inc. *      All rights reserved. * *	Permission to copy all or part of this material for any purpose is *	granted provided that the above copyright notice and this paragraph *	are duplicated in all copies.  THIS SOFTWARE IS PROVIDED ``AS IS'' *	AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT *	LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *	FOR A PARTICULAR PURPOSE. */static char     rcsid[] = "$Id: cache.c,v 1.1.1.1 2001/08/10 20:49:27 bonze Exp $";#include	<sys/types.h>#include        <sys/param.h>#include        <sys/socket.h>#include        <sys/time.h>#include        <sys/file.h>#include        <sys/wait.h>#include        <net/if.h>#include        <netinet/in.h>#include	<ctype.h>#include	<string.h>#include	<stdio.h>#if defined(AUTOTEST)#include	<unistd.h>#endif	/* AUTOTEST */#include	"radius.h"#include	"cache.h"static CONST HASHVAL * _hlist_search PROTO((HASHLIST ** list,						CONST HASHKEY * key, int len));static HASHLIST * _hlist_locate PROTO((HASHLIST ** list, CONST HASHKEY * key,					int len));static void _hlist_expire PROTO((HASHLIST ** list));static int _key_expired PROTO((HASHLIST * elem));static int _idle_expired PROTO((HASHLIST * elem));static time_t _calc_expiration PROTO((time_t duration));#if defined(AUTOTEST)int             count[BUCKETS];	/* allocater storage for statistics */#define	log_err	printf		/* debug output */#else	/* AUTOTEST */#define	log_err#endif	/* AUTOTEST */static CACHE   *cache = NULL;/* * Initialise the given cache.  Return 0 if successful, -1 if problems arise. */intcache_init (){	int             buckets = BUCKETS;	int             i;	if (cache != (CACHE *) NULL)	/* Already init'd */	{		return -1;	}	cache = (CACHE *) malloc (sizeof (*cache));	if (cache == (CACHE *) NULL)	{		return -1;	}	cache->buckets = buckets;	for (i = 0; i < buckets; i++)	{		cache->table[i] = (HASHLIST *) 0;#if defined(AUTOTEST)		count[i] = 0;#endif	}	return 0;} /* end of cache_init () *//* * Search the cache for the indicated key. *  * Return a pointer to the associated value or (HASHVAL *)0 if the key is not * found */CONST HASHVAL *cache_search (key, len)CONST HASHKEY  *key;int             len;{	int             bucket;	if (len > MAX_KEY_LEN)	{		return (CONST HASHVAL *) 0;	}	bucket = hash (key, len, cache->buckets);	if (cache->table[bucket])	{		return _hlist_search (&cache->table[bucket], key, len);	}	else	{		return (CONST HASHVAL *) 0;	}} /* end of cache_search () *//* * Insert the given info into the cache. *  * Checks for duplicate records. *  * Return TRUE if inserted, else FALSE. */intcache_insert (key, key_len, val, val_len, duration, idle)CONST HASHKEY  *key;int             key_len;CONST HASHVAL  *val;int             val_len;time_t          duration;time_t          idle;{	int             bucket;	HASHLIST       *elem;	CONST HASHVAL  *res;	if ((key_len > MAX_KEY_LEN) || (val_len > MAX_VAL_LEN))	{		return FALSE;	}	bucket = hash (key, key_len, cache->buckets);	res = _hlist_search (&cache->table[bucket], key, key_len);	if (res && (res != ELEM_DELETED))	{		return FALSE;	/* already in table, delete first */	}	elem = (HASHLIST *) malloc (sizeof (*elem));	if (!elem)	{		return FALSE;	}	else	{		elem->next = cache->table[bucket];		memcpy (elem->key, key, (size_t) key_len);		memcpy (elem->val, val, (size_t) val_len);		elem->time = _calc_expiration (duration);		if (idle)		{			elem->idle = _calc_expiration (idle);			elem->idling = TRUE;		}		else		{			elem->idling = FALSE;		}		cache->table[bucket] = elem;#if defined(AUTOTEST)		count[bucket]++;#endif#if(0)		printf ("cache_insert(key<%d><%s>, val<%d><%s>)\n",			key_len, elem->key, val_len, elem->val);#endif		return TRUE;	}} /* end of cache_insert () *//* * Delete the given info from the given cache. *  * Return TRUE if deleted, else FALSE. */intcache_delete (key, len)CONST HASHKEY  *key;int             len;{	int             bucket;	int             result = FALSE;	HASHLIST       *cur;	HASHLIST       *prev = (HASHLIST *) 0;	HASHLIST      **list;	if (len > MAX_KEY_LEN)	{		return FALSE;	}	bucket = hash (key, len, cache->buckets);	list = &cache->table[bucket];	for (cur = *list; cur; prev = cur, cur = cur->next)	{		if (memcmp (key, cur->key, len) == 0)		{			if (prev)			{				prev->next = cur->next;			}			else			{				*list = cur->next;			}			free (cur);			result = TRUE;			break;		}	}	return result;} /* end of cache_delete () *//* * Update the idle time for this entry *  * Return TRUE if elem has idling enabled, else FALSE. */intcache_idle_update (key, len, idle)CONST HASHKEY  *key;int             len;time_t          idle;{	int             bucket;	HASHLIST       *elem;	if (len > MAX_KEY_LEN)	{		return FALSE;	}	bucket = hash (key, len, cache->buckets);	elem = _hlist_locate (&cache->table[bucket], key, len);	elem->idle = _calc_expiration (idle);	return elem->idling;} /* end of cache_idle_update () *//* * Search the cache for expired keys and delete them. */voidcache_expire (){	int             ix;	for (ix = 0; ix < cache->buckets; ix++)	{		_hlist_expire (&cache->table[ix]);	}} /* end of cache_expire () *//* * Search the given hash list for the indicated key. *  * Return a pointer to the associated elem or (HASHLIST *)0 if the key is not * found. */static HASHLIST *_hlist_locate (list, key, len)HASHLIST      **list;CONST HASHKEY  *key;int             len;{	HASHLIST       *cur;	HASHLIST       *prev;	HASHLIST       *retval = (HASHLIST *) 0;	prev = (HASHLIST *) 0;	for (cur = *list; cur; prev = cur, cur = cur->next)	{		if (memcmp (key, cur->key, len) == 0)		{			retval = cur;			break;		}	}	return retval;} /* end of _hlist_locate () *//* * Search the given hash list for the indicated key. *  * Return a pointer to the associated value or (HASHVAL *)0 if the key is not * found. *  * For efficiency, delete the search entry if it has expired and return * ELEM_DELETED. *  * Does NOT update the idle timer. */static CONST HASHVAL *_hlist_search (list, key, len)HASHLIST      **list;CONST HASHKEY  *key;int             len;{	HASHLIST       *cur;	HASHLIST       *prev;	HASHVAL        *retval = (HASHVAL *) 0;	prev = (HASHLIST *) 0;	for (cur = *list; cur; prev = cur, cur = cur->next)	{		if (memcmp (key, cur->key, len) == 0)		{			retval = cur->val;			break;		}	}	if (retval)	{		if ((_key_expired (cur) == TRUE) ||		    ((cur->idling == TRUE) && (_idle_expired (cur) == TRUE)))		{			/* delete it now */			if (prev)			{				prev->next = cur->next;			}			else			{				*list = cur->next;			}			retval = ELEM_DELETED;			free (cur);		}	}	return (CONST HASHVAL *) retval;} /* end of _hlist_search () *//* * Search for and delete all expired keys */static void_hlist_expire (list)HASHLIST      **list;{	HASHLIST       *cur;	HASHLIST       *prev;	prev = (HASHLIST *) 0;	for (cur = *list; cur; prev = cur, cur = cur->next)	{		if (_key_expired (cur))		{			if (prev)			{				prev->next = cur->next;			}			else			{				*list = cur->next;			}			free (cur);		}	}} /* end of _hlist_expire () *//* * Return TRUE if the key has expired */static int_key_expired (elem)HASHLIST       *elem;{	time_t          curtime;	curtime = time ((time_t *) 0);	if (curtime == -1)	{		log_err ("_key_expired(): time() err\n");		return TRUE;	}	if (curtime > elem->time)	{		return TRUE;	}	else	{		return FALSE;	}} /* end of _key_expired () *//* * Return TRUE if the idle timer has expired */static int_idle_expired (elem)HASHLIST       *elem;{	time_t          curtime;	curtime = time ((time_t *) 0);	if (curtime == -1)	{		log_err ("_key_expired(): time() err\n");		return TRUE;	}	if (curtime > elem->idle)	{		return TRUE;	}	else	{		return FALSE;	}} /* end of _idle_expired () *//* * Calculate the time of expiration */static          time_t_calc_expiration (duration)time_t          duration;{	time_t          curtime;	curtime = time ((time_t *) 0);	if (curtime == -1)	{		log_err ("_calc_expiration(): time() err\n");		return duration;	}	curtime += duration;	return curtime;} /* end of _calc_expiration () *//**********************************************************	CRC-16 Byte Look-up Table <initial crc=0>		P(x) = a001 = 1 + x^2 + x^15 + x^16	This table was automatically generated by 'gencrc'	-- Do _NOT_ modify this table manually ! --	Table generated on Thu Oct  5 16:45:34 1995**********************************************************/unsigned short  crc_16_lookup[256] ={	0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,	0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,	0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,	0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,	0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,	0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,	0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,	0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,	0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,	0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,	0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,	0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,	0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,	0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,	0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,	0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,	0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,	0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,	0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,	0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,	0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,	0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,	0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,	0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,	0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,	0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,	0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,	0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,	0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,	0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,	0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,	0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040};/*-----------------------------------------------------------------------	unsigned short hash(key, len, buckets)	Calculate the CRC-16 of a key, modulo MODULUS.		uses the x^16 + x^15 + x^2 + 1 CRC-16 algorithm	Return the 16 bit crc number for a key, mod BUCKETS.	Uses a 256 entry table lookup.		NOTE: 17 (_not_ 16) terms [x^16 ... x^0]		X^16 + X^15 + X^2 + 1			= 1 1000 0000 0000 0101			= 18005			  ^ implicit value (17th bit)		Inverting the bit order yields			= 1010 0000 0000 0001 1			= a0011			      ^ implicit value (17th  bit)--------------------------------------------------------------------*/u_shorthash (key, len, buckets)CONST HASHKEY  *key;int             len;int             buckets;{	u_short         crc;	u_short         n;	int             i;	crc = 0;	for (i = len; i; i--)	{		n = *key++;		n ^= crc;		crc = crc_16_lookup[n & 0xff] ^ (crc >> 8);	}	return (unsigned int) crc % (unsigned int) buckets;} /* end of hash () */#if defined(AUTOTEST)/**********************************************************************			Test code**********************************************************************/intmain (argc, argv)int             argc;char          **argv;{	int             i;	int             least;	int             len;	int             most;	int             stat;	FILE           *fd;	HASHVAL        *val;	char           *words;	/* typically, /usr/dict/words */	char            buf[101];	if (argc < 2)	{		words = "/usr/dict/words";	}	else	{		words = argv[1];	}	cache_init ();	fd = fopen (words, "r");	if (!fd)	{		printf ("Error opening '%s'\n", words);		exit (-1);	}	while (fgets (buf, 100, fd) != (char *) 0)	{		len = strlen (buf);		if (buf[len - 1] == '\n')		{			buf[len - 1] = '\0';			len--;		}		len = MIN ((size_t) MAX_KEY_LEN, strlen (buf));		buf[len + 1] = '\0';		stat = cache_insert (buf, len + 1, buf, len + 1, 0);		printf ("Insert key <%s>: %s\n",			buf, (stat == TRUE) ? "GOOD" : "BAD");	}	least = most = 0;	for (i = 0; i < BUCKETS; i++)	{		if (count[i] < least)		{			least = count[i];		}		else if (count[i] > most)		{			most = count[i];		}	}	printf ("\n\nShortest List Len=%d, Longest List Len=%d\n\n",		least, most);	for (i = 0; i < BUCKETS; i++)	{		if ((i % 10) == 0)		{			printf ("\ncount[%4x]= ", i);		}		printf ("%4d ", count[i]);	}	printf ("\n\n");	rewind (fd);	while (fgets (buf, 100, fd) != (char *) 0)	{		char           *msg;		len = strlen (buf);		if (buf[len - 1] == '\n')		{			buf[len - 1] = '\0';			len--;		}		len = MIN ((size_t) MAX_KEY_LEN, strlen (buf));		buf[len + 1] = '\0';		val = (HASHVAL *) cache_search (buf, len + 1);		if (val && (val != ELEM_DELETED))		{			msg = "GOOD search";		}		else if (val == ELEM_DELETED)		{			msg = "DELETED before search";		}		else		{			msg = "BAD return from search";		}		if (val != ELEM_DELETED)		{			printf ("Search key <%s, %s>: %s\n", buf, val, msg);		}		else		{			printf ("Search key <%s>: %s\n", buf, msg);		}	}	rewind (fd);	while (fgets (buf, 100, fd) != (char *) 0)	{		len = strlen (buf);		if (buf[len - 1] == '\n')		{			buf[len - 1] = '\0';			len--;		}		len = MIN ((size_t) MAX_KEY_LEN, strlen (buf));		buf[len + 1] = '\0';		stat = cache_delete (buf, len + 1);		printf ("Delete key <%s>: %s\n",			buf, (stat == TRUE) ? "GOOD" : "BAD");	}	fclose (fd);	return 0;} /* end of main () */#endif	/* AUTOTEST */

⌨️ 快捷键说明

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