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