Annotation of cf/registry.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * IPFlow Collector
                      3:  * Copyright (c) 2003 Christophe Fillot.
                      4:  * E-mail: [email protected]
                      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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.