cfbb13f43dfb40419a9db32bcd7c6217fa195cd7
[awesomized/libmemcached] / lib / memcached_get.c
1 #include "common.h"
2 #include "memcached_io.h"
3
4 /*
5 What happens if no servers exist?
6 */
7 char *memcached_get(memcached_st *ptr, char *key, size_t key_length,
8 size_t *value_length,
9 uint32_t *flags,
10 memcached_return *error)
11 {
12 return memcached_get_by_key(ptr, NULL, 0, key, key_length, value_length,
13 flags, error);
14 }
15
16 char *memcached_get_by_key(memcached_st *ptr,
17 char *master_key, size_t master_key_length,
18 char *key, size_t key_length,
19 size_t *value_length,
20 uint32_t *flags,
21 memcached_return *error)
22 {
23 char *value;
24 size_t dummy_length;
25 uint32_t dummy_flags;
26 memcached_return dummy_error;
27
28 /* Request the key */
29 *error= memcached_mget_by_key(ptr,
30 master_key,
31 master_key_length,
32 &key, &key_length, 1);
33
34 value= memcached_fetch(ptr, NULL, NULL,
35 value_length, flags, error);
36 /* This is for historical reasons */
37 if (*error == MEMCACHED_END)
38 *error= MEMCACHED_NOTFOUND;
39
40 if (value == NULL)
41 return NULL;
42
43 (void)memcached_fetch(ptr, NULL, NULL,
44 &dummy_length, &dummy_flags,
45 &dummy_error);
46 WATCHPOINT_ASSERT(dummy_length == 0);
47
48 return value;
49 }
50
51 memcached_return memcached_mget(memcached_st *ptr,
52 char **keys, size_t *key_length,
53 unsigned int number_of_keys)
54 {
55 return memcached_mget_by_key(ptr, NULL, 0, keys, key_length, number_of_keys);
56 }
57
58 memcached_return memcached_mget_by_key(memcached_st *ptr,
59 char *master_key, size_t master_key_length,
60 char **keys, size_t *key_length,
61 unsigned int number_of_keys)
62 {
63 unsigned int x;
64 memcached_return rc= MEMCACHED_NOTFOUND;
65 char *get_command= "get ";
66 uint8_t get_command_length= 4;
67 unsigned int master_server_key= 0;
68
69 LIBMEMCACHED_MEMCACHED_MGET_START();
70 ptr->cursor_server= 0;
71
72 if (number_of_keys == 0)
73 return MEMCACHED_NOTFOUND;
74
75 if (ptr->number_of_hosts == 0)
76 return MEMCACHED_NO_SERVERS;
77
78 if (key_test(keys, key_length, number_of_keys) == MEMCACHED_BAD_KEY_PROVIDED)
79 return MEMCACHED_BAD_KEY_PROVIDED;
80
81 if (ptr->flags & MEM_SUPPORT_CAS)
82 {
83 get_command= "gets ";
84 get_command_length= 5;
85 }
86
87 if (master_key && master_key_length)
88 master_server_key= memcached_generate_hash(ptr, master_key, master_key_length);
89
90 /*
91 Here is where we pay for the non-block API. We need to remove any data sitting
92 in the queue before we start our get.
93
94 It might be optimum to bounce the connection if count > some number.
95 */
96 for (x= 0; x < ptr->number_of_hosts; x++)
97 {
98 if (memcached_server_response_count(&ptr->hosts[x]))
99 {
100 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
101
102 if (ptr->flags & MEM_NO_BLOCK)
103 (void)memcached_io_write(&ptr->hosts[x], NULL, 0, 1);
104
105 while(memcached_server_response_count(&ptr->hosts[x]))
106 (void)memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result);
107 }
108 }
109
110 /*
111 If a server fails we warn about errors and start all over with sending keys
112 to the server.
113 */
114 for (x= 0; x < number_of_keys; x++)
115 {
116 unsigned int server_key;
117
118 if (master_server_key)
119 server_key= master_server_key;
120 else
121 server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
122
123 if (memcached_server_response_count(&ptr->hosts[server_key]) == 0)
124 {
125 rc= memcached_connect(&ptr->hosts[server_key]);
126
127 if (rc != MEMCACHED_SUCCESS)
128 continue;
129
130 if ((memcached_io_write(&ptr->hosts[server_key], get_command, get_command_length, 0)) == -1)
131 {
132 rc= MEMCACHED_SOME_ERRORS;
133 continue;
134 }
135 WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 0);
136 memcached_server_response_increment(&ptr->hosts[server_key]);
137 WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 1);
138 }
139
140 if ((memcached_io_write(&ptr->hosts[server_key], keys[x], key_length[x], 0)) == -1)
141 {
142 memcached_server_response_reset(&ptr->hosts[server_key]);
143 rc= MEMCACHED_SOME_ERRORS;
144 continue;
145 }
146
147 if ((memcached_io_write(&ptr->hosts[server_key], " ", 1, 0)) == -1)
148 {
149 memcached_server_response_reset(&ptr->hosts[server_key]);
150 rc= MEMCACHED_SOME_ERRORS;
151 continue;
152 }
153 }
154
155 /*
156 Should we muddle on if some servers are dead?
157 */
158 for (x= 0; x < ptr->number_of_hosts; x++)
159 {
160 if (memcached_server_response_count(&ptr->hosts[x]))
161 {
162 /* We need to do something about non-connnected hosts in the future */
163 if ((memcached_io_write(&ptr->hosts[x], "\r\n", 2, 1)) == -1)
164 {
165 rc= MEMCACHED_SOME_ERRORS;
166 }
167 }
168 }
169
170 LIBMEMCACHED_MEMCACHED_MGET_END();
171 return rc;
172 }