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 *
kvs_create(int num_buckets,int num_entries)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
kvs_destroy(kvs_t * ht)46 kvs_destroy(kvs_t *ht)
47 {
48 free(ht->kvs_table);
49 free(ht->kvs_cont);
50 free(ht);
51 }
52 /*----------------------------------------------------------------------------*/
53 int
kvs_insert(kvs_t * ht,_key_t const key,void * const value)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 *
kvs_remove(kvs_t * ht,_key_t const key)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 *
kvs_search(kvs_t * ht,_key_t const key)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