Extended consistent hash logic to handle splice (should distribute keys much
[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 unsigned int range;
17
18 range= (MEMCACHED_WHEEL_SIZE / ptr->number_of_hosts);
19
20 /* Seed the Wheel */
21 memset(ptr->wheel, 0, sizeof(unsigned int) * MEMCACHED_WHEEL_SIZE);
22
23 for (latch= y= x= 0; x < MEMCACHED_WHEEL_SIZE; x++, latch++)
24 {
25 if (latch == MEMCACHED_STRIDE)
26 {
27 y++;
28 if (y == ptr->number_of_hosts)
29 y= 0;
30 latch= 0;
31 }
32
33 ptr->wheel[x]= y;
34 }
35 }
36
37 static void host_reset(memcached_server_st *host, char *hostname, unsigned int port,
38 memcached_connection type)
39 {
40 memset(host, 0, sizeof(memcached_server_st));
41 memcpy(host->hostname, hostname, strlen(hostname));
42 host->port= port;
43 host->fd= -1;
44 host->type= type;
45 host->read_ptr= host->read_buffer;
46 host->write_ptr= host->write_buffer;
47 host->sockaddr_inited= MEMCACHED_NOT_ALLOCATED;
48 }
49
50 memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
51 {
52 unsigned int x;
53 uint16_t count;
54 memcached_server_st *new_host_list;
55
56 if (!list)
57 return MEMCACHED_SUCCESS;
58
59 count= list[0].count;
60
61 new_host_list=
62 (memcached_server_st *)realloc(ptr->hosts,
63 sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
64
65 if (!new_host_list)
66 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
67
68 ptr->hosts= new_host_list;
69
70 for (x= 0; x < count; x++)
71 {
72 WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
73 host_reset(&ptr->hosts[ptr->number_of_hosts], list[x].hostname,
74 list[x].port, list[x].type);
75 ptr->number_of_hosts++;
76 }
77 ptr->hosts[0].count= ptr->number_of_hosts;
78
79 rebalance_wheel(ptr);
80
81 return MEMCACHED_SUCCESS;
82 }
83
84 memcached_return memcached_server_add_unix_socket(memcached_st *ptr, char *filename)
85 {
86 if (!filename)
87 return MEMCACHED_FAILURE;
88
89 return server_add(ptr, filename, 0, MEMCACHED_CONNECTION_UNIX_SOCKET);
90 }
91
92 memcached_return memcached_server_add_udp(memcached_st *ptr,
93 char *hostname,
94 unsigned int port)
95 {
96 if (!port)
97 port= MEMCACHED_DEFAULT_PORT;
98
99 if (!hostname)
100 hostname= "localhost";
101
102 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_UDP);
103 }
104
105 memcached_return memcached_server_add(memcached_st *ptr,
106 char *hostname,
107 unsigned int port)
108 {
109 if (!port)
110 port= MEMCACHED_DEFAULT_PORT;
111
112 if (!hostname)
113 hostname= "localhost";
114
115 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_TCP);
116 }
117
118 static memcached_return server_add(memcached_st *ptr, char *hostname,
119 unsigned int port,
120 memcached_connection type)
121 {
122 memcached_server_st *new_host_list;
123 LIBMEMCACHED_MEMCACHED_SERVER_ADD_START();
124
125
126 new_host_list= (memcached_server_st *)realloc(ptr->hosts,
127 sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
128 if (!new_host_list)
129 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
130
131 ptr->hosts= new_host_list;
132
133 host_reset(&ptr->hosts[ptr->number_of_hosts], hostname, port, type);
134 ptr->number_of_hosts++;
135 ptr->hosts[0].count++;
136
137 rebalance_wheel(ptr);
138
139 LIBMEMCACHED_MEMCACHED_SERVER_ADD_END();
140
141 return MEMCACHED_SUCCESS;
142 }
143
144 memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
145 char *hostname, unsigned int port,
146 memcached_return *error)
147 {
148 unsigned int count;
149 memcached_server_st *new_host_list;
150
151 if (!hostname)
152 return ptr;
153
154 if (!port)
155 port= MEMCACHED_DEFAULT_PORT;
156
157 /* Increment count for hosts */
158 count= 1;
159 if (ptr != NULL)
160 {
161 count+= ptr[0].count;
162 }
163
164 new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
165 if (!new_host_list)
166 {
167 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
168 return NULL;
169 }
170
171 host_reset(&new_host_list[count-1], hostname, port, MEMCACHED_CONNECTION_TCP);
172 new_host_list[0].count++;
173
174
175 *error= MEMCACHED_SUCCESS;
176 return new_host_list;
177 }
178
179 unsigned int memcached_server_list_count(memcached_server_st *ptr)
180 {
181 if (ptr == NULL)
182 return 0;
183
184 return ptr[0].count;
185 }
186
187 void memcached_server_list_free(memcached_server_st *ptr)
188 {
189 if (ptr == NULL)
190 return;
191
192 free(ptr);
193 }