1 /*
2  * cache.c  general cache manager
3  *
4  * Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
5  *               1998-                           <masaki-c@is.aist-nara.ac.jp>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21 */
22 /* $Id: cache.c,v 1.5 2003/07/21 23:06:47 chikama Exp $ */
23 
24 #include "config.h"
25 #include <stdio.h>
26 #include <limits.h>
27 #include <glib.h>
28 #include "portab.h"
29 #include "cache.h"
30 
31 /* maximum cache size (in MB) */
32 #ifndef CACHE_TOTALSIZE
33 #define CACHE_TOTALSIZE 20
34 #endif
35 
36 static int     totalsize;     /* total size in cache */
37 static int     id = 0;        /* Id of cache object  */
38 static boolean dummyfalse = FALSE; /* dummy in_use flag */
39 static boolean dummytrue  = TRUE;  /* dummy in_use flag */
40 
41 /*
42  * static methods
43 */
44 static void remove_in_cache(cacher *id);
45 
46 /*
47  * Remove data in cache
48  *   id: cache handler
49 */
remove_in_cache(cacher * id)50 static void remove_in_cache(cacher *id) {
51 	cacheinfo *ip = id->top;
52 	cacheinfo *ic = ip->next;
53 
54 	while(ic->next != NULL) {
55 		if (!(boolean)*(ic->in_use)) {
56 			if (ic->refcnt-- == 0) {
57 				totalsize -= ic->size;
58 				if (ic->next != NULL) {
59 					ip->next = ic->next;
60 				} else {
61 					ip->next = NULL;
62 				}
63 				id->free_(ic->data);
64 			}
65 		} else {
66 			ip = ic;
67 		}
68 		g_free(ic);
69 		ic = ip->next;
70 	}
71 	return;
72 }
73 
74 /*
75  * Create new cache object
76  *   delcallback: callback function for delete cache data object
77  *   return: new cache handler
78 */
cache_new(void * delcallback)79 cacher *cache_new(void *delcallback) {
80 	cacher *c = g_new0(cacher, 1);
81 
82 	c->id = id;
83 	c->top = g_new0(cacheinfo, 1);
84 	c->top->next = NULL;
85 	c->top->in_use = &dummytrue;
86 	c->free_ = delcallback;
87 	id++;
88 	return c;
89 }
90 
91 /*
92  * Insert data to cache
93  *   id    : cache handler
94  *   key   : data key
95  *   data  : data to be cached
96  *   size  : data size
97  *   in_use: in_use mark pointer, if in_use is TRUE, dont remove from cache
98 */
cache_insert(cacher * id,int key,void * data,int size,boolean * in_use)99 void cache_insert(cacher *id, int key, void *data, int size, boolean *in_use) {
100 	cacheinfo *i = id->top;
101 
102 	if (CACHE_TOTALSIZE <= (totalsize >> 20)) {
103 		remove_in_cache(id);
104 	}
105 
106 	while(i->next != NULL) {
107 		i = i->next;
108 	}
109 
110 	i->key = key;
111 	i->data = data;
112 	i->size = size;
113 	i->next = g_new0(cacheinfo, 1);
114 	i->next->next = NULL;
115 	if (in_use) {
116 		i->in_use = in_use;
117 	} else {
118 		i->in_use = &dummyfalse;
119 	}
120 	totalsize += size;
121 }
122 
123 /*
124  * Search data in cache
125  *   id : cache handler
126  *   key: data search key
127  *   return: pointer to cached data
128 */
cache_foreach(cacher * id,int key)129 void *cache_foreach(cacher *id, int key) {
130 	cacheinfo *i = id->top;
131 
132 	while(i != NULL) {
133 		if (i->key == key) {
134 			if (INT_MAX < i->refcnt) {
135 				i->refcnt++;
136 			}
137 			return i->data;
138 		}
139 		i = i->next;
140 	}
141 	return NULL;
142 }
143