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