MEMCACHED_BEHAVIOR_RETRY_TIMEOUT added for timeout
[awesomized/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 if (ptr)
65 host->next_retry= ptr->retry_timeout;
66 host->sockaddr_inited= MEMCACHED_NOT_ALLOCATED;
67 }
68
69 void server_list_free(memcached_st *ptr, memcached_server_st *servers)
70 {
71 unsigned int x;
72
73 if (servers == NULL)
74 return;
75
76 for (x= 0; x < servers->count; x++)
77 if (servers[x].address_info)
78 freeaddrinfo(servers[x].address_info);
79
80 if (ptr && ptr->call_free)
81 ptr->call_free(ptr, servers);
82 else
83 free(servers);
84 }
85
86 memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
87 {
88 unsigned int x;
89 uint16_t count;
90 memcached_server_st *new_host_list;
91
92 if (!list)
93 return MEMCACHED_SUCCESS;
94
95 count= list[0].count;
96
97 if (ptr->call_realloc)
98 new_host_list=
99 (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts,
100 sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
101 else
102 new_host_list=
103 (memcached_server_st *)realloc(ptr->hosts,
104 sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
105
106 if (!new_host_list)
107 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
108
109 ptr->hosts= new_host_list;
110
111 for (x= 0; x < count; x++)
112 {
113 WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
114 host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname,
115 list[x].port, list[x].type);
116 ptr->number_of_hosts++;
117 }
118 ptr->hosts[0].count= ptr->number_of_hosts;
119
120 if (ptr->number_of_hosts > 1)
121 qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers);
122
123 rebalance_wheel(ptr);
124
125 return MEMCACHED_SUCCESS;
126 }
127
128 memcached_return memcached_server_add_unix_socket(memcached_st *ptr, char *filename)
129 {
130 if (!filename)
131 return MEMCACHED_FAILURE;
132
133 return server_add(ptr, filename, 0, MEMCACHED_CONNECTION_UNIX_SOCKET);
134 }
135
136 memcached_return memcached_server_add_udp(memcached_st *ptr,
137 char *hostname,
138 unsigned int port)
139 {
140 if (!port)
141 port= MEMCACHED_DEFAULT_PORT;
142
143 if (!hostname)
144 hostname= "localhost";
145
146 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_UDP);
147 }
148
149 memcached_return memcached_server_add(memcached_st *ptr,
150 char *hostname,
151 unsigned int port)
152 {
153 if (!port)
154 port= MEMCACHED_DEFAULT_PORT;
155
156 if (!hostname)
157 hostname= "localhost";
158
159 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_TCP);
160 }
161
162 static memcached_return server_add(memcached_st *ptr, char *hostname,
163 unsigned int port,
164 memcached_connection type)
165 {
166 memcached_server_st *new_host_list;
167 LIBMEMCACHED_MEMCACHED_SERVER_ADD_START();
168
169
170 if (ptr->call_realloc)
171 new_host_list= (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts,
172 sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
173 else
174 new_host_list= (memcached_server_st *)realloc(ptr->hosts,
175 sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
176 if (new_host_list == NULL)
177 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
178
179 ptr->hosts= new_host_list;
180
181 host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], hostname, port, type);
182 ptr->number_of_hosts++;
183 ptr->hosts[0].count++;
184
185 if (ptr->number_of_hosts > 1)
186 qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers);
187
188 rebalance_wheel(ptr);
189
190 LIBMEMCACHED_MEMCACHED_SERVER_ADD_END();
191
192 return MEMCACHED_SUCCESS;
193 }
194
195 memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
196 char *hostname, unsigned int port,
197 memcached_return *error)
198 {
199 unsigned int count;
200 memcached_server_st *new_host_list;
201
202 if (hostname == NULL || error == NULL)
203 return NULL;
204
205 if (!port)
206 port= MEMCACHED_DEFAULT_PORT;
207
208 /* Increment count for hosts */
209 count= 1;
210 if (ptr != NULL)
211 {
212 count+= ptr[0].count;
213 }
214
215 new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
216 if (!new_host_list)
217 {
218 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
219 return NULL;
220 }
221
222 host_reset(NULL, &new_host_list[count-1], hostname, port, MEMCACHED_CONNECTION_TCP);
223
224 /* Backwards compatibility hack */
225 new_host_list[0].count++;
226
227 count= new_host_list[0].count;
228
229 if (new_host_list[0].count > 1)
230 qsort(new_host_list, count, sizeof(memcached_server_st), compare_servers);
231
232 new_host_list[0].count= count;
233
234
235 *error= MEMCACHED_SUCCESS;
236 return new_host_list;
237 }
238
239 unsigned int memcached_server_list_count(memcached_server_st *ptr)
240 {
241 if (ptr == NULL)
242 return 0;
243
244 return ptr[0].count;
245 }
246
247 void memcached_server_list_free(memcached_server_st *ptr)
248 {
249 server_list_free(NULL, ptr);
250 }