|
1 |
|
2 #include <assert.h> |
|
3 |
|
4 #include "command.h" |
|
5 #include "../common.h" |
|
6 |
|
7 static char *memcache_cmd_names[MEMCACHE_CMD_MAX] = { |
|
8 NULL, // MEMCACHE_CMD_INVALID |
|
9 "get", // MEMCACHE_CMD_FETCH_GET |
|
10 "set", // MEMCACHE_CMD_STORE_SET |
|
11 "add", // MEMCACHE_CMD_STORE_ADD |
|
12 "replace", // MEMCACHE_CMD_STORE_REPLACE |
|
13 "append", // MEMCACHE_CMD_STORE_APPEND |
|
14 "prepend" // MEMCACHE_CMD_STORE_PREPEND |
|
15 }; |
|
16 |
|
17 /* |
|
18 static struct memcache_reply_info { |
|
19 enum memcache_reply type; |
|
20 char *name; |
|
21 int has_data; |
|
22 |
|
23 } *memcache_cmd_replies[MEMCACHE_RPL_MAX] = { |
|
24 MEMCACHE_RPL_INVALID, |
|
25 |
|
26 MEMCACHE_RPL_ERROR, |
|
27 MEMCACHE_RPL_CLIENT_ERROR, |
|
28 MEMCACHE_RPL_SERVER_ERROR, |
|
29 |
|
30 // MEMCACHE_CMD_FETCH_* |
|
31 MEMCACHE_RPL_VALUE, |
|
32 MEMCACHE_RPL_END, |
|
33 |
|
34 // MEMCACHE_CMD_STORE_* |
|
35 MEMCACHE_RPL_STORED, |
|
36 MEMCACHE_RPL_NOT_STORED, |
|
37 MEMCACHE_RPL_EXISTS, |
|
38 MEMCACHE_RPL_NOT_FOUND, |
|
39 |
|
40 }; |
|
41 |
|
42 */ |
|
43 |
|
44 int memcache_cmd_init (struct memcache_cmd *cmd, enum memcache_command cmd_type, struct memcache_key *key, struct memcache_obj *obj) { |
|
45 // shouldn't already have a request header yet? |
|
46 assert(cmd->req_header == NULL); |
|
47 |
|
48 // allocate the request header |
|
49 if ((cmd->req_header = evbuffer_new()) == NULL) |
|
50 ERROR("evbuffer_new"); |
|
51 |
|
52 // format the command |
|
53 if (memcache_cmd_format_header(cmd->req_header, cmd_type, key, obj)) |
|
54 goto error; |
|
55 |
|
56 // XXX: prepare the rest |
|
57 |
|
58 // success |
|
59 return 0; |
|
60 |
|
61 error: |
|
62 if (cmd->req_header) |
|
63 evbuffer_free(cmd->req_header); |
|
64 |
|
65 return -1; |
|
66 } |
|
67 |
|
68 int memcache_cmd_format_header (struct evbuffer *buf, enum memcache_command cmd_type, struct memcache_key *key, struct memcache_obj *obj) { |
|
69 char *cmd_name; |
|
70 |
|
71 // valid command |
|
72 assert(cmd_type < MEMCACHE_CMD_MAX); |
|
73 |
|
74 if (cmd_type == MEMCACHE_CMD_INVALID) |
|
75 ERROR("invalid command"); |
|
76 |
|
77 // map the command to a string |
|
78 cmd_name = memcache_cmd_names[cmd_type]; |
|
79 |
|
80 // format the request header |
|
81 switch (cmd_type) { |
|
82 case MEMCACHE_CMD_FETCH_GET: |
|
83 assert(key != NULL && obj == NULL); |
|
84 assert(key->len > 0 && key->buf != NULL); |
|
85 |
|
86 if (evbuffer_add_printf(buf, "%s %*s\r\n", cmd_name, (int) key->len, key->buf) == -1) |
|
87 ERROR("evbuffer_add_printf"); |
|
88 |
|
89 break; |
|
90 |
|
91 case MEMCACHE_CMD_STORE_SET: |
|
92 case MEMCACHE_CMD_STORE_ADD: |
|
93 case MEMCACHE_CMD_STORE_REPLACE: |
|
94 case MEMCACHE_CMD_STORE_APPEND: |
|
95 case MEMCACHE_CMD_STORE_PREPEND: |
|
96 assert(key != NULL && obj != NULL); |
|
97 assert(key->len > 0 && key->buf != NULL); |
|
98 assert(obj->bytes > 0); |
|
99 |
|
100 if (evbuffer_add_printf(buf, "%s %*s %u %lu %zu\r\n", cmd_name, (int) key->len, key->buf, obj->flags, obj->exptime, obj->bytes)) |
|
101 ERROR("evbuffer_add_printf"); |
|
102 |
|
103 break; |
|
104 |
|
105 case MEMCACHE_CMD_STORE_CAS: |
|
106 default: |
|
107 // XXX: not supported yet/invalid |
|
108 assert(0); |
|
109 }; |
|
110 |
|
111 // success |
|
112 return 0; |
|
113 |
|
114 error: |
|
115 return -1; |
|
116 |
|
117 } |
|
118 |
|
119 int memcache_cmd_parse_header (struct evbuffer *buf, char **header_data, enum memcache_reply *reply_type, struct memcache_key *key, struct memcache_obj *obj, int *has_data) { |
|
120 // XXX: implement |
|
121 assert(0); |
|
122 } |
|
123 |