Merge.
[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 void host_reset(memcached_st *ptr, memcached_server_st *host,
35 char *hostname, unsigned int port,
36 memcached_connection type)
37 {
38 memset(host, 0, sizeof(memcached_server_st));
39 strncpy(host->hostname, hostname, MEMCACHED_MAX_HOST_LENGTH - 1);
40 host->root= ptr ? ptr : NULL;
41 host->port= port;
42 host->fd= -1;
43 host->type= type;
44 host->read_ptr= host->read_buffer;
45 host->sockaddr_inited= MEMCACHED_NOT_ALLOCATED;
46 }
47
48 void server_list_free(memcached_st *ptr, memcached_server_st *servers)
49 {
50 unsigned int x;
51
52 if (servers == NULL)
53 return;
54
55 for (x= 0; x < servers->count; x++)
56 if (servers[x].address_info)
57 freeaddrinfo(servers[x].address_info);
58
59 if (ptr && ptr->call_free)
60 ptr->call_free(ptr, servers);
61 else
62 free(servers);
63 }
64
65 memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
66 {
67 unsigned int x;
68 uint16_t count;
69 memcached_server_st *new_host_list;
70
71 if (!list)
72 return MEMCACHED_SUCCESS;
73
74 count= list[0].count;
75
76 if (ptr->call_realloc)
77 new_host_list=
78 (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts,
79 sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
80 else
81 new_host_list=
82 (memcached_server_st *)realloc(ptr->hosts,
83 sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
84
85 if (!new_host_list)
86 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
87
88 ptr->hosts= new_host_list;
89
90 for (x= 0; x < count; x++)
91 {
92 WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
93 host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname,
94 list[x].port, list[x].type);
95 ptr->number_of_hosts++;
96 }
97 ptr->hosts[0].count= ptr->number_of_hosts;
98
99 rebalance_wheel(ptr);
100
101 return MEMCACHED_SUCCESS;
102 }
103
104 memcached_return memcached_server_add_unix_socket(memcached_st *ptr, char *filename)
105 {
106 if (!filename)
107 return MEMCACHED_FAILURE;
108
109 return server_add(ptr, filename, 0, MEMCACHED_CONNECTION_UNIX_SOCKET);
110 }
111
112 memcached_return memcached_server_add_udp(memcached_st *ptr,
113 char *hostname,
114 unsigned int port)
115 {
116 if (!port)
117 port= MEMCACHED_DEFAULT_PORT;
118
119 if (!hostname)
120 hostname= "localhost";
121
122 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_UDP);
123 }
124
125 memcached_return memcached_server_add(memcached_st *ptr,
126 char *hostname,
127 unsigned int port)
128 {
129 if (!port)
130 port= MEMCACHED_DEFAULT_PORT;
131
132 if (!hostname)
133 hostname= "localhost";
134
135 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_TCP);
136 }
137
138 static memcached_return server_add(memcached_st *ptr, char *hostname,
139 unsigned int port,
140 memcached_connection type)
141 {
142 memcached_server_st *new_host_list;
143 LIBMEMCACHED_MEMCACHED_SERVER_ADD_START();
144
145
146 if (ptr->call_realloc)
147 new_host_list= (memcached_server_st *)ptr->call_realloc(ptr, ptr->hosts,
148 sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
149 else
150 new_host_list= (memcached_server_st *)realloc(ptr->hosts,
151 sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
152 if (new_host_list == NULL)
153 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
154
155 ptr->hosts= new_host_list;
156
157 host_reset(ptr, &ptr->hosts[ptr->number_of_hosts], hostname, port, type);
158 ptr->number_of_hosts++;
159 ptr->hosts[0].count++;
160
161 rebalance_wheel(ptr);
162
163 LIBMEMCACHED_MEMCACHED_SERVER_ADD_END();
164
165 return MEMCACHED_SUCCESS;
166 }
167
168 memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
169 char *hostname, unsigned int port,
170 memcached_return *error)
171 {
172 unsigned int count;
173 memcached_server_st *new_host_list;
174
175 if (hostname == NULL || error == NULL)
176 return NULL;
177
178 if (!port)
179 port= MEMCACHED_DEFAULT_PORT;
180
181 /* Increment count for hosts */
182 count= 1;
183 if (ptr != NULL)
184 {
185 count+= ptr[0].count;
186 }
187
188 new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
189 if (!new_host_list)
190 {
191 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
192 return NULL;
193 }
194
195 host_reset(NULL, &new_host_list[count-1], hostname, port, MEMCACHED_CONNECTION_TCP);
196
197 /* Backwards compatibility hack */
198 new_host_list[0].count++;
199
200
201 *error= MEMCACHED_SUCCESS;
202 return new_host_list;
203 }
204
205 unsigned int memcached_server_list_count(memcached_server_st *ptr)
206 {
207 if (ptr == NULL)
208 return 0;
209
210 return ptr[0].count;
211 }
212
213 void memcached_server_list_free(memcached_server_st *ptr)
214 {
215 server_list_free(NULL, ptr);
216 }