forked from 5ujinKang/Key-Value-Store
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasic_kvs.c
More file actions
137 lines (113 loc) · 3.26 KB
/
basic_kvs.c
File metadata and controls
137 lines (113 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* Basic key value store in C.
* only runs on 1 thread.
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#define NUM_BUCKETS 1024
#define VALUE_SIZE 32
typedef struct Entry {
size_t key;
char value[VALUE_SIZE];
struct Entry* next;
} Entry;
typedef struct {
Entry* buckets[NUM_BUCKETS];
pthread_mutex_t locks[NUM_BUCKETS];
} KVStore;
// Simple hash function
size_t hash(size_t key) {
return key % NUM_BUCKETS;
}
// Initialize KV store
KVStore* kvstore_create() {
KVStore* store = malloc(sizeof(KVStore));
for (size_t i = 0; i < NUM_BUCKETS; i++) {
store->buckets[i] = NULL;
pthread_mutex_init(&store->locks[i], NULL);
}
return store;
}
// Set operation (insert/update)
void kv_set(KVStore* store, size_t key, const char* value) {
size_t idx = hash(key);
pthread_mutex_lock(&store->locks[idx]);
Entry* curr = store->buckets[idx];
while (curr) {
if (curr->key == key) {
strncpy(curr->value, value, VALUE_SIZE);
printf("[SET] Updated key %zu -> %s\n", key, value);
pthread_mutex_unlock(&store->locks[idx]);
return;
}
curr = curr->next;
}
// Key not found, insert new
Entry* new_entry = malloc(sizeof(Entry));
new_entry->key = key;
strncpy(new_entry->value, value, VALUE_SIZE);
new_entry->next = store->buckets[idx];
store->buckets[idx] = new_entry;
printf("[SET] Inserted key %zu -> %s\n", key, value);
pthread_mutex_unlock(&store->locks[idx]);
}
// Get operation
int kv_get(KVStore* store, size_t key, char* out_value) {
if (!store) {
printf("[GET] ERROR: KV store is NULL\n");
return 0;
}
size_t idx = hash(key);
pthread_mutex_lock(&store->locks[idx]);
Entry* curr = store->buckets[idx];
while (curr) {
if (curr->key == key) {
strncpy(out_value, curr->value, VALUE_SIZE);
pthread_mutex_unlock(&store->locks[idx]);
printf("[GET] Key %zu -> %s\n", key, out_value);
return 1;
}
curr = curr->next;
}
pthread_mutex_unlock(&store->locks[idx]);
printf("[GET] Key %zu not found\n", key);
return 0; // Not found
}
// Cleanup
void kvstore_destroy(KVStore** store_ptr) {
if (!store_ptr || !*store_ptr) return;
KVStore* store = *store_ptr;
for (size_t i = 0; i < NUM_BUCKETS; i++) {
Entry* curr = store->buckets[i];
while (curr) {
Entry* tmp = curr;
curr = curr->next;
free(tmp);
}
pthread_mutex_destroy(&store->locks[i]);
}
free(store);
*store_ptr = NULL; // nullify pointer
printf("[DESTROY] KV store destroyed and pointer set to NULL\n");
}
// ---------------- TEST ---------------- //
int main() {
KVStore* store = kvstore_create();
kv_set(store, 1, "Hello");
kv_set(store, 2, "World");
char value[VALUE_SIZE];
kv_get(store, 1, value);
kv_get(store, 2, value);
kv_get(store, 3, value);
// Safe destroy
kvstore_destroy(&store);
// Try to access after destroy safely
if (!store) {
printf("Cannot access store after destroy (pointer is NULL)\n");
} else {
kv_get(store, 1, value); // won't happen
}
return 0;
}