Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

mntd_volume_hash.c

00001 /***************************************************************************
00002  * CVSID: $Id: mntd_volume_hash.c,v 1.14 2004/08/07 15:10:47 stefanb Exp $
00003  *
00004  * mntd_volume_hash.c : Volume Manager hash functions for MNT daemon
00005  *
00006  * Copyright (C) 2004 Stefan Bambach, <sbambach@gmx.net>
00007  *
00008  * Licensed under the GNU General Public License 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  **************************************************************************/
00025  
00026 #ifdef HAVE_CONFIG_H
00027 #  include <config.h>
00028 #endif
00029 
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <glib.h>
00035 #include "mntd_volume_hash.h"
00036 #include "errmanager.h"
00037 #include "dbug_mem.h"
00038 
00039 
00040 /* private prototypes */
00041 PHASHMAPELEMENT new_HashMapElement(PHASHMAP phm, 
00042                                                 void (*cb_free_element)(void *data), 
00043                                                 const char *key, void *userdata);
00044 void hashmapelement_destroy(PHASHMAPELEMENT phme);
00045 int hashmap_init(PHASHMAP phm);
00046 void hashmap_destroy(PHASHMAP phm);
00047 int hashmap_hash_element(const void *obj);
00048 int hashmap_compare_element(const void *obj1, const void *obj2);
00049 void hashmap_free_element(void *userdata);
00050 
00051 /* public prototypes */
00052 int hashmap_add(PHASHMAP phm, const char *key, void *data);
00053 int hashmap_remove(PHASHMAP phm, const char *key);
00054 int hashmap_size(PHASHMAP phm);
00055 int hashmap_contains(PHASHMAP phm, const char *key);
00056 int hashmap_get(PHASHMAP phm, const char *key, void **userdata);
00057 int hashmap_update(PHASHMAP phm, const char *key, void *userdata);
00058 int hashmap_foreach_call_function(PHASHMAP phm, int (*func)(void *data, void *userdata), void *userdata);
00059 
00060 
00072 PHASHMAPELEMENT 
00073 new_HashMapElement(PHASHMAP phm, void (*cb_free_element)(void *userdata), const char *key, void *userdata)
00074 {
00075     PHASHMAPELEMENT phme = NULL;
00076     
00077     g_assert(phm!=NULL);
00078     g_assert(cb_free_element!=NULL);
00079     g_assert(key!=NULL);
00080     
00081     //MSG_DEBUG("new_HashMapElement('%s', %p) called", key, userdata);
00082     
00083     phme = (PHASHMAPELEMENT) malloc(sizeof(HASHMAPELEMENT));
00084     if (phme == NULL) {
00085         MSG_ERR("Out of memory");
00086         return NULL;
00087     }
00088     
00089     // clear structure
00090     memset(phme, 0, sizeof(HASHMAPELEMENT));
00091     
00092     // initialize data
00093     phme->phm = phm;
00094     phme->key = strdup(key);
00095     phme->userdata = userdata;
00096     
00097     // private methods
00098     phme->destroy = hashmapelement_destroy;
00099     phme->cb_free_element = cb_free_element;
00100     
00101     //MSG_DEBUG("new_HashMapElement('%s', %p) returned %p", key, userdata, phme);
00102     
00103     // return object
00104     return phme;
00105 }
00106 
00107 
00113 void
00114 hashmapelement_destroy(PHASHMAPELEMENT phme)
00115 {
00116     g_assert(phme!=NULL);
00117     
00118     //MSG_DEBUG("hashmapelement_destroy(%p) called (key='%s', userdata=%p)", phme, phme->key, phme->userdata);
00119 
00120     // free memory for key
00121     if (phme->key != NULL) {
00122         free(phme->key);
00123         phme->key = NULL;
00124     }
00125     
00126     // call user defined functions
00127     if ((phme->cb_free_element != NULL) && (phme->userdata != NULL)) {
00128         phme->cb_free_element(phme->userdata);
00129         phme->cb_free_element = NULL;
00130         phme->userdata = NULL;
00131     }
00132     
00133     // clear structure
00134     if (phme != NULL) {
00135         memset(phme, 0, sizeof(HASHMAPELEMENT));
00136         free(phme);
00137         phme = NULL;
00138     }
00139     
00140     return;
00141 }
00142 
00143 
00144 PHASHMAP 
00145 new_HashMap(unsigned int bucket, 
00146     void (*cb_free_element)(void *userdata)
00147     )
00148 {
00149     PHASHMAP phm = NULL;
00150     
00151     g_assert(cb_free_element!=NULL);
00152     
00153     phm = (PHASHMAP) malloc(sizeof(HASHMAP));
00154     if (phm == NULL) {
00155         MSG_ERR("Out of memory");
00156         return NULL;
00157     }
00158     
00159     // clear structure
00160     memset(phm, 0, sizeof(HASHMAP));
00161     
00162     // no. of buckets (should be prime num)
00163     if (bucket>0) {
00164         phm->bucket = bucket;
00165     } else {
00166         MSG_INF("bucket not correctly setup. Using %d as default.", DEFAULT_BUCKETS);
00167         phm->bucket = DEFAULT_BUCKETS;
00168     }
00169 
00170     // private methods
00171     phm->init = hashmap_init;
00172     phm->destroy = hashmap_destroy;
00173     // hash, compare, free methods (implemented for each object)
00174     phm->hash = hashmap_hash_element;
00175     phm->compare = hashmap_compare_element;
00176     phm->free = hashmap_free_element;
00177     phm->cb_free_element = cb_free_element;
00178     
00179     // public methods
00180     phm->add = hashmap_add;
00181     phm->remove = hashmap_remove;
00182     phm->size = hashmap_size;
00183     phm->contains = hashmap_contains;
00184     phm->get = hashmap_get;
00185     phm->update = hashmap_update;
00186     phm->foreach = hashmap_foreach_call_function;
00187     
00188     // call constructor
00189     if(phm->init(phm) == -1) {
00190         free(phm);
00191         phm = NULL;
00192     }
00193 
00194     // return object
00195     return phm;
00196 }
00197 
00198 
00205 int
00206 hashmap_init(PHASHMAP phm)
00207 {
00208     CHTbl *htbl = NULL;
00209 
00210     if (phm==NULL) {
00211         return -1;
00212     }
00213     
00214     // get mem for structure
00215     htbl = (CHTbl *) malloc(sizeof(CHTbl));
00216     if (htbl == NULL) {
00217         MSG_ERR("not enough mem for hash table");
00218         return -1;
00219     }
00220     
00221     // initialize table
00222     if (chtbl_init(htbl, phm->bucket, phm->hash, phm->compare, phm->free) != 0) {
00223         MSG_ERR("could not initialize hash table");
00224         if (htbl!=NULL) free(htbl);
00225         return -1;
00226     }
00227     
00228     // store table pointer
00229     phm->hm = htbl;
00230     
00231     // return success
00232     return 0;
00233 }
00234 
00235 
00242 void
00243 hashmap_destroy(PHASHMAP phm)
00244 {
00245     CHTbl *htbl = NULL;
00246     
00247     if (phm == NULL) {
00248         return;
00249     }
00250     
00251     if (phm->hm != NULL) {
00252         htbl = phm->hm;
00253         chtbl_destroy(htbl);
00254         free(htbl);
00255         phm->hm = NULL;
00256     }
00257     
00258     if (phm != NULL) {
00259         memset(phm, 0, sizeof(HASHMAP));
00260         free(phm);
00261         phm = NULL;
00262     }
00263     
00264     return;
00265 }
00266 
00267 
00274 int
00275 hashmap_hash_element(const void *obj)
00276 {
00277     char *key = NULL;
00278     unsigned int crc = 0;
00279     
00280     if (obj==NULL) {
00281         MSG_EMERG("Hashmap HASH function called with wrong parameter ! (obj=0x%08x)", obj);
00282         return 0;
00283     }
00284     
00285     key = ((PHASHMAPELEMENT)obj)->key;
00286     while(*key!='\0') {
00287         crc += *key++;
00288     }
00289     
00290     return crc;
00291 }
00292 
00293 
00301 int
00302 hashmap_compare_element(const void *obj1, const void *obj2)
00303 {
00304     char *key1 = NULL;
00305     char *key2 = NULL;
00306     int res = 0;
00307     
00308     if ((obj1==NULL) || (obj2==NULL)) {
00309         MSG_EMERG("Hashmap MATCH function called with wrong parameters ! (obj1=0x%08x, obj2=0x%08x)", obj1, obj2);
00310         return 0;
00311     }
00312         
00313     if (obj1==obj2) {
00314         MSG_EMERG("Hashmap MATCH function called with identical parameters ! (obj1=obj2=0x%08x)", obj1);
00315         return 0;
00316     }
00317         
00318     key1 = ((PHASHMAPELEMENT)obj1)->key;
00319     key2 = ((PHASHMAPELEMENT)obj2)->key;
00320 
00321     res = strcmp(key1, key2);
00322 
00323     return res == 0 ? 1 : 0;
00324 }
00325 
00326 
00332 void
00333 hashmap_free_element(void *userdata)
00334 {
00335     PHASHMAPELEMENT phme = NULL;
00336     
00337     //MSG_DEBUG("hashmap_free_element(%p) called.", userdata);
00338     
00339     if (userdata != NULL) {
00340         phme = (PHASHMAPELEMENT) userdata;
00341         phme->destroy(phme);
00342         phme = NULL;
00343     }
00344     
00345     return;
00346 }
00347 
00348 
00358 int
00359 hashmap_add(PHASHMAP phm, const char *key, void *data)
00360 {
00361     PHASHMAPELEMENT phme = NULL;
00362     int retval;
00363     
00364     if ((phm==NULL) || (key==NULL)) {
00365         return -1;
00366     }
00367 
00368     phme = new_HashMapElement(phm, phm->cb_free_element, key, data);
00369     if (phme == NULL) {
00370         return -1;
00371     }
00372     
00373     retval = chtbl_insert(phm->hm, phme);
00374     
00375     return retval;
00376 }
00377 
00378 
00385 int
00386 hashmap_remove(PHASHMAP phm, const char *key)
00387 {
00388     PHASHMAPELEMENT tmp = NULL;
00389     PHASHMAPELEMENT phme = NULL;
00390     void *chtbl_data = NULL;
00391     int retval;
00392     
00393     if ((phm==NULL) || ((phm->hm)==NULL) || (key==NULL)) {
00394         return -1;
00395     }
00396 
00397     tmp = new_HashMapElement(phm, phm->cb_free_element, key, NULL);
00398     if (tmp == NULL) {
00399         return -1;
00400     }
00401     
00402     chtbl_data = (void *)tmp;
00403     retval = chtbl_remove(phm->hm, &chtbl_data);
00404     if (retval == 0) {
00405         if (chtbl_data != NULL) {
00406             phme = (PHASHMAPELEMENT)chtbl_data;
00407             if (phme != tmp) {
00408                 if (phme != NULL) {
00409                     phme->destroy(phme);
00410                 }
00411             }
00412         }
00413     }
00414     tmp->destroy(tmp); tmp=NULL;
00415     
00416     return retval;
00417 }
00418 
00419 
00425 int
00426 hashmap_size(PHASHMAP phm)
00427 {
00428     if ((phm==NULL) || ((phm->hm)==NULL)) {
00429         return -1;
00430     }
00431     
00432     return chtbl_size(phm->hm);
00433 }
00434 
00435 
00442 int
00443 hashmap_contains(PHASHMAP phm, const char *key)
00444 {
00445     PHASHMAPELEMENT tmp = NULL;
00446     void *data = NULL;
00447     int retval;
00448     
00449     if ((phm==NULL) || ((phm->hm)==NULL)) {
00450         return 0;
00451     }
00452     
00453     tmp = new_HashMapElement(phm, phm->cb_free_element, key, NULL);
00454     if (tmp == NULL) {
00455         return 0;
00456     }
00457     
00458     data = (void *)tmp;
00459     retval = chtbl_lookup(phm->hm, &data);
00460     tmp->destroy(tmp); tmp=NULL;
00461     
00462     return (retval==0) ? 1 : 0;
00463 }
00464 
00465 
00473 int
00474 hashmap_get(PHASHMAP phm, const char *key, void **userdata)
00475 {
00476     PHASHMAPELEMENT tmp = NULL;
00477     void *data = NULL;
00478     int retval;
00479     
00480     if ((phm==NULL) || ((phm->hm)==NULL)) {
00481         return -1;
00482     }
00483     
00484     tmp = new_HashMapElement(phm, phm->cb_free_element, key, NULL);
00485     if (tmp == NULL) {
00486         return -1;
00487     }
00488     
00489     data = (void *)tmp;
00490     retval = chtbl_lookup(phm->hm, &data);
00491     tmp->destroy(tmp); tmp=NULL;
00492     
00493     if (retval != 0) {
00494         *userdata = NULL;
00495         return -1;
00496     }
00497     
00498     // return data
00499     *userdata = ((PHASHMAPELEMENT)data)->userdata;
00500     return 0;
00501 }
00502 
00503 
00511 int
00512 hashmap_update(PHASHMAP phm, const char *key, void *userdata)
00513 {
00514     PHASHMAPELEMENT tmp = NULL;
00515     PHASHMAPELEMENT phme = NULL;
00516     void *data = NULL;
00517     int retval;
00518     
00519     if ((phm==NULL) || (key==NULL)) {
00520         return -1;
00521     }
00522 
00523     if (phm->contains(phm, key)) {
00524         tmp = new_HashMapElement(phm, phm->cb_free_element, key, NULL);
00525         if (tmp == NULL) {
00526             return -1;
00527         }
00528     
00529         data = (void *)tmp;
00530         retval = chtbl_lookup(phm->hm, &data);
00531         tmp->destroy(tmp); tmp=NULL;
00532         
00533         if (retval == 0) {
00534             phme = (PHASHMAPELEMENT)data;
00535             if (phme != NULL) {
00536                 phme->cb_free_element(phme->userdata);
00537                 phme->userdata = userdata;
00538             }
00539         }
00540     }
00541     
00542     return -1;
00543 }
00544 
00545 
00553 int
00554 hashmap_foreach_call_function(PHASHMAP phm, 
00555     int (*func)(void *data, void *userdata), 
00556    void *userdata)
00557 {
00558     int i=0;
00559     
00560     if ((phm==NULL) || (func==NULL) || (phm->hm==NULL)) {
00561         return -1;
00562     }
00563 
00564     for (i=0; i<phm->hm->buckets; i++) {
00565         list_for_each_call(&phm->hm->table[i], func, userdata);
00566     }
00567     
00568     return 0;
00569 }

Generated on Wed Mar 30 13:43:27 2005 for Mntd by  doxygen 1.3.9.1