Annotation of cf/registry.c, revision 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.