MEMCACHED_BAD_KEY_PROVIDED has been added as an error type. When libmemcached
[m6w6/libmemcached] / lib / memcached_hosts.c
1 #include <memcached.h>
2 #include "common.h"
3
4 /* Protoypes (static) */
5 static memcached_return server_add(memcached_st *ptr, char *hostname,
6 unsigned int port,
7 memcached_connection type);
8
9 #define MEMCACHED_WHEEL_SIZE 1024
10 #define MEMCACHED_STRIDE 4
11 static void rebalance_wheel(memcached_st *ptr)
12 {
13 unsigned int x;
14 unsigned int y;
15 unsigned int latch;
16
17 /* Seed the Wheel */
18 memset(ptr->wheel, 0, sizeof(unsigned int) * MEMCACHED_WHEEL_SIZE);
19
20 for (latch= y= x= 0; x < MEMCACHED_WHEEL_SIZE; x++, latch++)
21 {
22 if (latch == MEMCACHED_STRIDE)
23 {
24 y++;
25 if (y == ptr->number_of_hosts)
26 y= 0;
27 latch= 0;
28 }
29
30 ptr->wheel[x]= y;
31 }
32 }
33
34 static int compare_servers(const void *p1, const void *p2)
35 {
36 int return_value;
37 memcached_server_st *a= (memcached_server_st *)p1;
38 memcached_server_st *b= (memcached_server_st *)p2;
39
40 return_value= strcmp(a->hostname, b->hostname);
41
42 if (return_value == 0)
43 {
44 if (a->port > b->port)
45 return_value++;
46 else
47 return_value--;
48 }
49
50 return return_value;
51 }
52
53 static void host_reset(memcached_st *ptr, memcached_server_st *host,
54 char *hostname, unsigned int port,
55 memcached_connection type)
56 {
57 memset(host, 0, sizeof(memcached_server_st));
58 strncpy(host->hostname, hostname, MEMCACHED_MAX_HOST_LENGTH - 1);
59 host->root= ptr ? ptr : NULL;
60 host->port= port;
61 host->fd= -1;
62 host->type= type;
63 host->read_ptr= host->read_buffer;
64 host->sockaddr_inited= MEMCACHED_NOT_ALLOCATED;
65 }
66
67 void server_list_free(memcached_st *ptr, memcached_server_st *servers)
68 {
69 unsigned int x;
70
71 if (servers == NULL)
72 return;
73
74 for (x= 0; x < servers->count; x++)
75 if (servers[x].address_info)
76 freeaddrinfo(servers[x].address_info);
77
78 if (ptr && ptr->call_free)
79 ptr->call_free(ptr, servers);
80 else
81 free(servers);
82 }
83
84 memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
85 {
86 unsigned int x;
87 uint16_t count;
88 memcached_server_st *new_host_list;
89
90 if (!list)
91 return MEMCACHED_SUCCESS;
92
93 count= list[0].count;
94
95 if (ptr->call_realloc)
96 new_host_list=
97 (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts,
98 sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
99 else
100 new_host_list=
101 (memcached_server_st *)realloc(ptr->hosts,
102 sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
103
104 if (!new_host_list)
105 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
106
107 ptr->hosts= new_host_list;
108
109 for (x= 0; x < count; x++)
110 {
111 WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
112 host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname,
113 list[x].port, list[x].type);
114 ptr->number_of_hosts++;
115 }
116 ptr->hosts[0].count= ptr->number_of_hosts;
117
118 if (ptr->number_of_hosts > 1)
119 qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers);
120
121 rebalance_wheel(ptr);
122
123 return MEMCACHED_SUCCESS;
124 }
125
126 memcached_return memcached_server_add_unix_socket(memcached_st *ptr, char *filename)
127 {
128 if (!filename)
129 return MEMCACHED_FAILURE;
130
131 return server_add(ptr, filename, 0, MEMCACHED_CONNECTION_UNIX_SOCKET);
132 }
133
134 memcached_return memcached_server_add_udp(memcached_st *ptr,
135 char *hostname,
136 unsigned int port)
137 {
138 if (!port)
139 port= MEMCACHED_DEFAULT_PORT;
140
141 if (!hostname)
142 hostname= "localhost";
143
144 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_UDP);
145 }
146
147 memcached_return memcached_server_add(memcached_st *ptr,
148 char *hostname,
149 unsigned int port)
150 {
151 if (!port)
152 port= MEMCACHED_DEFAULT_PORT;
153
154 if (!hostname)
155 hostname= "localhost";
156
157 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_TCP);
158 }
159
160 static memcached_return server_add(memcached_st *ptr, char *hostname,
161 unsigned int port,
162 memcached_connection type)
163 {
164 memcached_server_st *new_host_list;
165 LIBMEMCACHED_MEMCACHED_SERVER_ADD_START();
166
167
168 if (ptr->call_realloc)
169 new_host_list= (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts,
170 sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
171 else
172 new_host_list= (memcached_server_st *)realloc(ptr->hosts,
173 sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
174 if (new_host_list == NULL)
175 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
176
177 ptr->hosts= new_host_list;
178
179 host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], hostname, port, type);
180 ptr->number_of_hosts++;
181 ptr->hosts[0].count++;
182
183 if (ptr->number_of_hosts > 1)
184 qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers);
185
186 rebalance_wheel(ptr);
187
188 LIBMEMCACHED_MEMCACHED_SERVER_ADD_END();
189
190 return MEMCACHED_SUCCESS;
191 }
192
193 memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
194 char *hostname, unsigned int port,
195 memcached_return *error)
196 {
197 unsigned int count;
198 memcached_server_st *new_host_list;
199
200 if (hostname == NULL || error == NULL)
201 return NULL;
202
203 if (!port)
204 port= MEMCACHED_DEFAULT_PORT;
205
206 /* Increment count for hosts */
207 count= 1;
208 if (ptr != NULL)
209 {
210 count+= ptr[0].count;
211 }
212
213 new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
214 if (!new_host_list)
215 {
216 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
217 return NULL;
218 }
219
220 host_reset(NULL, &new_host_list[count-1], hostname, port, MEMCACHED_CONNECTION_TCP);
221
222 /* Backwards compatibility hack */
223 new_host_list[0].count++;
224
225 count= new_host_list[0].count;
226
227 if (new_host_list[0].count > 1)
228 qsort(new_host_list, count, sizeof(memcached_server_st), compare_servers);
229
230 new_host_list[0].count= count;
231
232
233 *error= MEMCACHED_SUCCESS;
234 return new_host_list;
235 }
236
237 unsigned int memcached_server_list_count(memcached_server_st *ptr)
238 {
239 if (ptr == NULL)
240 return 0;
241
242 return ptr[0].count;
243 }
244
245 void memcached_server_list_free(memcached_server_st *ptr)
246 {
247 server_list_free(NULL, ptr);
248 }