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