00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
00082
00083 phme = (PHASHMAPELEMENT) malloc(sizeof(HASHMAPELEMENT));
00084 if (phme == NULL) {
00085 MSG_ERR("Out of memory");
00086 return NULL;
00087 }
00088
00089
00090 memset(phme, 0, sizeof(HASHMAPELEMENT));
00091
00092
00093 phme->phm = phm;
00094 phme->key = strdup(key);
00095 phme->userdata = userdata;
00096
00097
00098 phme->destroy = hashmapelement_destroy;
00099 phme->cb_free_element = cb_free_element;
00100
00101
00102
00103
00104 return phme;
00105 }
00106
00107
00113 void
00114 hashmapelement_destroy(PHASHMAPELEMENT phme)
00115 {
00116 g_assert(phme!=NULL);
00117
00118
00119
00120
00121 if (phme->key != NULL) {
00122 free(phme->key);
00123 phme->key = NULL;
00124 }
00125
00126
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
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
00160 memset(phm, 0, sizeof(HASHMAP));
00161
00162
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
00171 phm->init = hashmap_init;
00172 phm->destroy = hashmap_destroy;
00173
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
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
00189 if(phm->init(phm) == -1) {
00190 free(phm);
00191 phm = NULL;
00192 }
00193
00194
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
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
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
00229 phm->hm = htbl;
00230
00231
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
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
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 }