/[dynamips]/trunk/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

Annotation of /trunk/registry.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations)
Sat Oct 6 16:06:49 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC3/registry.c
File MIME type: text/plain
File size: 9254 byte(s)
dynamips-0.2.6-RC3

1 dpavlin 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