/[dynamips]/upstream/dynamips-0.2.5/registry.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/dynamips-0.2.5/registry.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sat Oct 6 16:01:44 2007 UTC (12 years, 2 months ago) by dpavlin
File MIME type: text/plain
File size: 9254 byte(s)
import 0.2.5 from upstream

1 /*
2 * IPFlow Collector
3 * Copyright (c) 2003 Christophe Fillot.
4 * E-mail: cf@utc.fr
5 *
6 * registry.c: Object Registry.
7 */
8
9 #define _GNU_SOURCE
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <stdarg.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <signal.h>
17 #include <fcntl.h>
18 #include <ctype.h>
19 #include <time.h>
20 #include <pthread.h>
21 #include <sys/time.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <assert.h>
26
27 #include "utils.h"
28 #include "hash.h"
29 #include "mempool.h"
30 #include "registry.h"
31
32 #define DEBUG_REGISTRY 0
33
34 static registry_t *registry = NULL;
35
36 #define REGISTRY_LOCK() pthread_mutex_lock(&registry->lock)
37 #define REGISTRY_UNLOCK() pthread_mutex_unlock(&registry->lock)
38
39 /* Initialize registry */
40 int registry_init(void)
41 {
42 registry_entry_t *p;
43 pthread_mutexattr_t attr;
44 size_t len;
45 int i;
46
47 registry = malloc(sizeof(*registry));
48 assert(registry != NULL);
49
50 pthread_mutexattr_init(&attr);
51 pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
52 pthread_mutex_init(&registry->lock,&attr);
53
54 /* initialize registry memory pool */
55 mp_create_fixed_pool(&registry->mp,"registry");
56
57 registry->ht_name_entries = REGISTRY_HT_NAME_ENTRIES;
58 registry->ht_type_entries = REGISTRY_MAX_TYPES;
59
60 /* initialize hash table for names, with sentinels */
61 len = registry->ht_name_entries * sizeof(registry_entry_t);
62 registry->ht_names = mp_alloc(&registry->mp,len);
63 assert(registry->ht_names != NULL);
64
65 for(i=0;i<registry->ht_name_entries;i++) {
66 p = &registry->ht_names[i];
67 p->hname_next = p->hname_prev = p;
68 }
69
70 /* initialize hash table for types, with sentinels */
71 len = registry->ht_type_entries * sizeof(registry_entry_t);
72 registry->ht_types = mp_alloc(&registry->mp,len);
73 assert(registry->ht_types != NULL);
74
75 for(i=0;i<registry->ht_type_entries;i++) {
76 p = &registry->ht_types[i];
77 p->htype_next = p->htype_prev = p;
78 }
79
80 return(0);
81 }
82
83 /* Insert a new entry */
84 static void registry_insert_entry(registry_entry_t *entry)
85 {
86 registry_entry_t *bucket;
87 u_int h_index;
88
89 /* insert new entry in hash table for names */
90 h_index = str_hash(entry->name) % registry->ht_name_entries;
91 bucket = &registry->ht_names[h_index];
92
93 entry->hname_next = bucket->hname_next;
94 entry->hname_prev = bucket;
95 bucket->hname_next->hname_prev = entry;
96 bucket->hname_next = entry;
97
98 /* insert new entry in hash table for object types */
99 bucket = &registry->ht_types[entry->object_type];
100
101 entry->htype_next = bucket->htype_next;
102 entry->htype_prev = bucket;
103 bucket->htype_next->htype_prev = entry;
104 bucket->htype_next = entry;
105 }
106
107 /* Remove a registry entry */
108 void registry_remove_entry(registry_entry_t *entry)
109 {
110 entry->hname_prev->hname_next = entry->hname_next;
111 entry->hname_next->hname_prev = entry->hname_prev;
112
113 entry->htype_prev->htype_next = entry->htype_next;
114 entry->htype_next->htype_prev = entry->htype_prev;
115
116 mp_free(entry);
117 }
118
119 /* Locate an entry */
120 static inline registry_entry_t *registry_find_entry(char *name,int object_type)
121 {
122 registry_entry_t *entry,*bucket;
123 u_int h_index;
124
125 h_index = str_hash(name) % registry->ht_name_entries;
126 bucket = &registry->ht_names[h_index];
127
128 for(entry=bucket->hname_next;entry!=bucket;entry=entry->hname_next)
129 if (!strcmp(entry->name,name) && (entry->object_type == object_type))
130 return entry;
131
132 return NULL;
133 }
134
135 /* Add a new entry to the registry */
136 int registry_add(char *name,int object_type,void *data)
137 {
138 registry_entry_t *entry;
139
140 if (!name)
141 return(-1);
142
143 REGISTRY_LOCK();
144
145 /* check if we have already a reference for this name */
146 if ((entry = registry_find_entry(name,object_type))) {
147 REGISTRY_UNLOCK();
148 return(-1);
149 }
150
151 /* create a new entry */
152 if (!(entry = mp_alloc(&registry->mp,sizeof(*entry)))) {
153 REGISTRY_UNLOCK();
154 return(-1);
155 }
156
157 entry->name = name;
158 entry->data = data;
159 entry->object_type = object_type;
160 entry->ref_count = 1; /* consider object is referenced by the caller */
161 registry_insert_entry(entry);
162
163 REGISTRY_UNLOCK();
164 return(0);
165 }
166
167 /* Delete an entry from the registry */
168 int registry_delete(char *name,int object_type)
169 {
170 registry_entry_t *entry;
171
172 if (!name) return(-1);
173
174 REGISTRY_LOCK();
175
176 if (!(entry = registry_find_entry(name,object_type))) {
177 REGISTRY_UNLOCK();
178 return(-1);
179 }
180
181 /* if the entry is referenced, just decrement ref counter */
182 if (--entry->ref_count > 0) {
183 REGISTRY_UNLOCK();
184 return(0);
185 }
186
187 registry_remove_entry(entry);
188 REGISTRY_UNLOCK();
189 return(0);
190 }
191
192 /* Find an entry (increment the reference count) */
193 void *registry_find(char *name,int object_type)
194 {
195 registry_entry_t *entry;
196 void *data;
197
198 if (!name) return NULL;
199
200 REGISTRY_LOCK();
201
202 if ((entry = registry_find_entry(name,object_type))) {
203 entry->ref_count++;
204 data = entry->data;
205 } else
206 data = NULL;
207
208 REGISTRY_UNLOCK();
209 return data;
210 }
211
212 /* Check if entry exists (does not change reference count) */
213 void *registry_exists(char *name,int object_type)
214 {
215 registry_entry_t *entry;
216 void *data = NULL;
217
218 if (!name)
219 return NULL;
220
221 REGISTRY_LOCK();
222 entry = registry_find_entry(name,object_type);
223 if (entry)
224 data = entry->data;
225 REGISTRY_UNLOCK();
226 return data;
227 }
228
229 /* Release a reference of an entry (decrement the reference count) */
230 int registry_unref(char *name,int object_type)
231 {
232 registry_entry_t *entry;
233 int res = -1;
234
235 if (!name) return(-1);
236
237 REGISTRY_LOCK();
238
239 if ((entry = registry_find_entry(name,object_type)))
240 {
241 entry->ref_count--;
242
243 #if DEBUG_REGISTRY
244 printf("Registry: object %s: ref_count = %d after unref.\n",
245 name, entry->ref_count);
246 #endif
247
248 if (entry->ref_count < 0) {
249 fprintf(stderr,"Registry: object %s (type %d): negative ref_count.\n",
250 name, object_type);
251 } else
252 res = 0;
253 }
254
255 REGISTRY_UNLOCK();
256 return(res);
257 }
258
259 /*
260 * Execute action on an object if its reference count is less or equal to
261 * the specified count.
262 */
263 int registry_exec_refcount(char *name,int object_type,int max_ref,int reg_del,
264 registry_exec obj_action,void *opt_arg)
265 {
266 registry_entry_t *entry;
267 int res = -1;
268 int status;
269
270 if (!name) return(-1);
271
272 REGISTRY_LOCK();
273
274 entry = registry_find_entry(name,object_type);
275
276 if (entry)
277 {
278 if (entry->ref_count <= max_ref)
279 {
280 status = TRUE;
281
282 if (obj_action != NULL)
283 status = obj_action(entry->data,opt_arg);
284
285 if (reg_del && status)
286 registry_remove_entry(entry);
287
288 res = 1;
289 } else
290 res = 0;
291 }
292
293 REGISTRY_UNLOCK();
294 return(res);
295 }
296
297 /* Delete object if unused */
298 int registry_delete_if_unused(char *name,int object_type,
299 registry_exec obj_destructor,void *opt_arg)
300 {
301 return(registry_exec_refcount(name,object_type,0,TRUE,
302 obj_destructor,opt_arg));
303 }
304
305 /* Execute a callback function for all objects of specified type */
306 int registry_foreach_type(int object_type,registry_foreach cb,
307 void *opt,int *err)
308 {
309 registry_entry_t *p,*bucket,*next;
310 int count = 0;
311
312 REGISTRY_LOCK();
313
314 bucket = &registry->ht_types[object_type];
315
316 for(p=bucket->htype_next;p!=bucket;p=next) {
317 next = p->htype_next;
318 if (cb) cb(p,opt,err);
319 count++;
320 }
321
322 REGISTRY_UNLOCK();
323 return(count);
324 }
325
326 /* Delete all objects of the specified type */
327 int registry_delete_type(int object_type,registry_exec cb,void *opt)
328 {
329 registry_entry_t *p,*bucket,*next;
330 int count = 0;
331 int status;
332
333 REGISTRY_LOCK();
334
335 bucket = &registry->ht_types[object_type];
336
337 for(p=bucket->htype_next;p!=bucket;p=next) {
338 next = p->htype_next;
339
340 if (p->ref_count == 0) {
341 status = TRUE;
342
343 if (cb != NULL)
344 status = cb(p->data,opt);
345
346 if (status) {
347 registry_remove_entry(p);
348 count++;
349 }
350 } else {
351 fprintf(stderr,"registry_delete_type: object \"%s\" (type %d) still "
352 "referenced (count=%d)\n",p->name,object_type,p->ref_count);
353 }
354 }
355
356 REGISTRY_UNLOCK();
357 return(count);
358 }
359
360 /* Dump the registry */
361 void registry_dump(void)
362 {
363 registry_entry_t *p,*bucket;
364 int i;
365
366 REGISTRY_LOCK();
367
368 printf("Registry dump:\n");
369
370 printf(" Objects (from name hash table):\n");
371
372 /* dump hash table of names */
373 for(i=0;i<registry->ht_name_entries;i++)
374 {
375 bucket = &registry->ht_names[i];
376
377 for(p=bucket->hname_next;p!=bucket;p=p->hname_next)
378 printf(" %s (type %d, ref_count=%d)\n",
379 p->name,p->object_type,p->ref_count);
380 }
381
382 printf("\n Objects classed by types:\n");
383
384 /* dump hash table of types */
385 for(i=0;i<registry->ht_type_entries;i++)
386 {
387 printf(" Type %d: ",i);
388
389 bucket = &registry->ht_types[i];
390 for(p=bucket->htype_next;p!=bucket;p=p->htype_next)
391 printf("%s(%d) ",p->name,p->ref_count);
392
393 printf("\n");
394 }
395
396 REGISTRY_UNLOCK();
397 }

  ViewVC Help
Powered by ViewVC 1.1.26