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