1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <assert.h> 5 #include <math.h> 6 #include <netinet/in.h> 7 #include <arpa/inet.h> 8 #include <sys/queue.h> 9 #include "debug.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 /* create an entry*/ 57 int idx; 58 59 assert(value); 60 61 assert(ht); 62 assert(ht->kvs_count <= ht->num_entries); 63 64 if (kvs_search(ht, key)) 65 return -1; 66 67 idx = key % ht->num_buckets; 68 assert(idx >=0 && idx < ht->num_buckets); 69 70 /* get a container */ 71 struct kvs_entry *ent; 72 if (!(ent = TAILQ_FIRST(&ht->kvs_free))) 73 return -1; 74 TAILQ_REMOVE(&ht->kvs_free, ent, link); 75 76 /* put the value to the container */ 77 ent->key = key; 78 ent->value = value; 79 80 /* insert the container */ 81 TAILQ_INSERT_TAIL(&ht->kvs_table[idx], ent, link); 82 ht->kvs_count++; 83 84 TRACE_DBG("%lX inserted to 0x%p\n", key, ht); 85 86 return 0; 87 } 88 /*----------------------------------------------------------------------------*/ 89 void * 90 kvs_remove(kvs_t *ht, _key_t const key) 91 { 92 struct kvs_entry *walk; 93 kvs_bucket_head *head; 94 95 head = &ht->kvs_table[key % ht->num_buckets]; 96 TAILQ_FOREACH(walk, head, link) { 97 if (key == walk->key) { 98 TAILQ_REMOVE(head, walk, link); 99 TAILQ_INSERT_TAIL(&ht->kvs_free, walk, link); 100 ht->kvs_count--; 101 102 TRACE_DBG("%lX removed from 0x%p\n", key, ht); 103 return walk->value; 104 } 105 } 106 107 return NULL; 108 } 109 /*----------------------------------------------------------------------------*/ 110 void * 111 kvs_search(kvs_t *ht, _key_t const key) 112 { 113 TRACE_DBG("look for %lX from 0x%p..\n", key, ht); 114 115 struct kvs_entry *walk; 116 kvs_bucket_head *head; 117 118 head = &ht->kvs_table[key % ht->num_buckets]; 119 TAILQ_FOREACH(walk, head, link) { 120 if (key == walk->key) 121 return walk->value; 122 } 123 124 return NULL; 125 } 126 /*----------------------------------------------------------------------------*/ 127