13
13
14
14
#include < numeric>
15
15
#include < string>
16
- #include < unordered_map>
17
16
18
17
#include " cacheX_protocol.hpp"
19
-
20
- static std::vector<Conn *> fd2conn;
21
-
22
- // TODO: Remove this
23
- static std::unordered_map<std::string, std::string> g_data ;
24
-
25
- typedef struct KeyValue {
26
- char *key;
27
- char *value;
28
- struct KeyValue *next ;
29
- } KeyValue ;
30
-
31
- KeyValue *hash_table[HASH_TABLE_SIZE] = { nullptr };
32
-
33
- // Hash function (djb2 algorithm)
34
- unsigned long hash_function ( const char *str) {
35
- unsigned long hash = 5381 ;
36
- int c ;
37
- while ((c = *str++)) {
38
- hash = ((hash << 5 ) + hash) + c; /* hash * 33 + c */
39
- }
40
- return hash % HASH_TABLE_SIZE ;
18
+ # include " common.hpp "
19
+ # include " hashmap.hpp "
20
+
21
+ static struct {
22
+ HMap db ;
23
+ std::vector<Conn *> fd2conn;
24
+ } g_data;
25
+
26
+ struct LookupKey {
27
+ struct HNode node ;
28
+ std::string key ;
29
+ };
30
+
31
+ struct Entry {
32
+ struct HNode node;
33
+ std::string key;
34
+ std::string str ;
35
+ } ;
36
+
37
+ static Entry * entry_new () {
38
+ Entry *ent = new Entry ();
39
+ return ent ;
41
40
}
42
41
43
- void store_set_command (const char *key, const char *value) {
44
- unsigned long index = hash_function (key);
45
-
46
- KeyValue *new_pair = (KeyValue *)malloc (sizeof (KeyValue));
47
- if (!new_pair) {
48
- fprintf (stderr, " [ERROR] Memory allocation failed for KeyValue\n " );
49
- return ;
50
- }
51
-
52
- new_pair->key = strdup (key);
53
- new_pair->value = strdup (value);
54
- if (!new_pair->key || !new_pair->value ) {
55
- fprintf (stderr, " [ERROR] Memory allocation failed for key/value\n " );
56
- free (new_pair);
57
- return ;
58
- }
59
-
60
- new_pair->next = hash_table[index];
61
- hash_table[index] = new_pair;
42
+ static void entry_del (Entry *ent) {
43
+ // if (ent->type == T_ZSET) {
44
+ // zset_clear(&ent->zset);
45
+ // }
46
+ delete ent;
62
47
}
63
48
64
- const char *fetch_get_command (const char *key) {
65
- unsigned long index = hash_function (key);
66
- KeyValue *entry = hash_table[index];
67
-
68
- while (entry) {
69
- if (strcmp (entry->key , key) == 0 ) {
70
- return entry->value ;
71
- }
72
- entry = entry->next ;
73
- }
74
- return nullptr ;
49
+ static bool entry_eq (HNode *node, HNode *key) {
50
+ struct Entry *ent = container_of (node, struct Entry , node);
51
+ struct LookupKey *keydata = container_of (key, struct LookupKey , node);
52
+ return ent->key == keydata->key ;
75
53
}
76
54
77
55
static void msg (int line_number, const char *format, ...) {
@@ -108,18 +86,39 @@ static int set_nonblocking(int sockfd) {
108
86
}
109
87
110
88
static void process_request (std::vector<std::string> &cmd, Response &out) {
89
+ LookupKey key;
111
90
if (cmd.size () == 2 && cmd[0 ] == " GET" ) {
112
- auto it = g_data.find (cmd[1 ]);
113
- if (it == g_data.end ()) {
91
+ key.key .swap (cmd[1 ]);
92
+ key.node .hcode = str_hash ((uint8_t *)key.key .data (), key.key .size ());
93
+ HNode *node = g_data.db .lookup (&key.node , &entry_eq);
94
+ if (!node) {
114
95
out.status = RES_NX;
115
96
return ;
116
97
} else {
117
- out.data .assign (it->second .begin (), it->second .end ());
98
+ Entry *ent = container_of (node, Entry, node);
99
+ out.data .assign (ent->str .begin (), ent->str .end ());
118
100
}
119
101
} else if (cmd.size () == 3 && cmd[0 ] == " SET" ) {
120
- g_data[cmd[1 ]] = std::move (cmd[2 ]);
102
+ key.key .swap (cmd[1 ]);
103
+ key.node .hcode = str_hash ((uint8_t *)key.key .data (), key.key .size ());
104
+ HNode *node = g_data.db .lookup (&key.node , &entry_eq);
105
+ if (node) {
106
+ Entry *ent = container_of (node, Entry, node);
107
+ ent->str .swap (cmd[2 ]);
108
+ } else {
109
+ Entry *ent = entry_new ();
110
+ ent->key .swap (key.key );
111
+ ent->node .hcode = key.node .hcode ;
112
+ ent->str .swap (cmd[2 ]);
113
+ g_data.db .insert (&ent->node );
114
+ }
121
115
} else if (cmd.size () == 2 && cmd[0 ] == " DEL" ) {
122
- g_data.erase (cmd[1 ]);
116
+ key.key .swap (cmd[1 ]);
117
+ key.node .hcode = str_hash ((uint8_t *)key.key .data (), key.key .size ());
118
+ HNode *node = g_data.db .hm_delete (&key.node , &entry_eq);
119
+ if (node) {
120
+ entry_del (container_of (node, Entry, node));
121
+ }
123
122
} else {
124
123
out.status = RES_ERR;
125
124
fprintf (stderr, " [ERROR] Invalid command.\n " );
@@ -317,15 +316,15 @@ void start_server() {
317
316
318
317
set_nonblocking (client_fd);
319
318
320
- if (fd2conn.size () <= (size_t )client_fd) {
321
- fd2conn.resize (client_fd + 1 );
319
+ if (g_data. fd2conn .size () <= (size_t )client_fd) {
320
+ g_data. fd2conn .resize (client_fd + 1 );
322
321
}
323
- if (fd2conn[client_fd] != nullptr ) {
322
+ if (g_data. fd2conn [client_fd] != nullptr ) {
324
323
fprintf (stderr,
325
324
" [WARNING] Reusing file descriptor %d for new connection.\n " ,
326
325
client_fd);
327
326
}
328
- fd2conn[client_fd] = new Conn{client_fd, true , false , false , {}, {}};
327
+ g_data. fd2conn [client_fd] = new Conn{client_fd, true , false , false , {}, {}};
329
328
event.events = EPOLLIN | EPOLLET;
330
329
event.data .fd = client_fd;
331
330
epoll_ctl (epoll_fd, EPOLL_CTL_ADD, client_fd, &event);
@@ -338,7 +337,7 @@ void start_server() {
338
337
continue ;
339
338
}
340
339
341
- Conn *conn = fd2conn[fd];
340
+ Conn *conn = g_data. fd2conn [fd];
342
341
if (events[i].events & EPOLLIN) {
343
342
handle_read (conn);
344
343
}
@@ -348,7 +347,7 @@ void start_server() {
348
347
if (conn->want_close ) {
349
348
epoll_ctl (epoll_fd, EPOLL_CTL_DEL, conn->fd , nullptr );
350
349
close (conn->fd );
351
- fd2conn[conn->fd ] = nullptr ;
350
+ g_data. fd2conn [conn->fd ] = nullptr ;
352
351
delete conn;
353
352
}
354
353
}
0 commit comments