1 #include "debug.h" 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <assert.h> 6 #include <math.h> 7 #include <netinet/in.h> 8 #include <arpa/inet.h> 9 #include <sys/queue.h> 10 #include "key_value_store.h" 11 #include "scalable_event.h" 12 13 /*----------------------------------------------------------------------------*/ 14 kvs_t * 15 kvs_create(int num_buckets, int num_entries) 16 { 17 int i; 18 kvs_t *ht = calloc(1, sizeof(kvs_t)); 19 if (!ht) 20 return NULL; 21 22 ht->num_buckets = num_buckets; 23 ht->num_entries = num_entries; 24 25 /* init the tables */ 26 if (!(ht->kvs_table = calloc(num_buckets, sizeof(kvs_bucket_head)))) { 27 free(ht); 28 return NULL; 29 } 30 for (i = 0; i < num_buckets; i++) 31 TAILQ_INIT(&ht->kvs_table[i]); 32 33 if (!(ht->kvs_cont = calloc(num_entries, sizeof(struct kvs_entry)))) { 34 free(ht->kvs_table); 35 free(ht); 36 return NULL; 37 } 38 TAILQ_INIT(&ht->kvs_free); 39 for (i = 0; i < num_entries; i++) 40 TAILQ_INSERT_TAIL(&ht->kvs_free, &ht->kvs_cont[i], link); 41 42 return ht; 43 } 44 /*----------------------------------------------------------------------------*/ 45 void 46 kvs_destroy(kvs_t *ht) 47 { 48 free(ht->kvs_table); 49 free(ht->kvs_cont); 50 free(ht); 51 } 52 /*----------------------------------------------------------------------------*/ 53 int 54 kvs_insert(kvs_t *ht, _key_t const key, void * const value) 55 { 56 #ifdef DBGMSG 57 __PREPARE_DBGLOGGING(); 58 #endif 59 /* create an entry*/ 60 int idx; 61 62 assert(value); 63 64 assert(ht); 65 assert(ht->kvs_count <= ht->num_entries); 66 67 if (kvs_search(ht, key)) 68 return -1; 69 70 idx = key % ht->num_buckets; 71 assert(idx >=0 && idx < ht->num_buckets); 72 73 /* get a container */ 74 struct kvs_entry *ent; 75 if (!(ent = TAILQ_FIRST(&ht->kvs_free))) 76 return -1; 77 TAILQ_REMOVE(&ht->kvs_free, ent, link); 78 79 /* put the value to the container */ 80 ent->key = key; 81 ent->value = value; 82 83 /* insert the container */ 84 TAILQ_INSERT_TAIL(&ht->kvs_table[idx], ent, link); 85 ht->kvs_count++; 86 87 TRACE_DBG("%lX inserted to 0x%p\n", key, ht); 88 89 return 0; 90 } 91 /*----------------------------------------------------------------------------*/ 92 void * 93 kvs_remove(kvs_t *ht, _key_t const key) 94 { 95 #ifdef DBGMSG 96 __PREPARE_DBGLOGGING(); 97 #endif 98 struct kvs_entry *walk; 99 kvs_bucket_head *head; 100 101 head = &ht->kvs_table[key % ht->num_buckets]; 102 TAILQ_FOREACH(walk, head, link) { 103 if (key == walk->key) { 104 TAILQ_REMOVE(head, walk, link); 105 TAILQ_INSERT_TAIL(&ht->kvs_free, walk, link); 106 ht->kvs_count--; 107 108 TRACE_DBG("%lX removed from 0x%p\n", key, ht); 109 return walk->value; 110 } 111 } 112 113 return NULL; 114 } 115 /*----------------------------------------------------------------------------*/ 116 void * 117 kvs_search(kvs_t *ht, _key_t const key) 118 { 119 #ifdef DBGMSG 120 __PREPARE_DBGLOGGING(); 121 #endif 122 TRACE_DBG("look for %lX from 0x%p..\n", key, ht); 123 124 struct kvs_entry *walk; 125 kvs_bucket_head *head; 126 127 head = &ht->kvs_table[key % ht->num_buckets]; 128 TAILQ_FOREACH(walk, head, link) { 129 if (key == walk->key) 130 return walk->value; 131 } 132 133 return NULL; 134 } 135 /*----------------------------------------------------------------------------*/ 136