fe62b4e9715da2d651da5869910fad2cabfc77cb
[awesomized/libmemcached] / libmemcached / server.c
1 /* LibMemcached
2 * Copyright (C) 2006-2009 Brian Aker
3 * All rights reserved.
4 *
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
7 *
8 * Summary: String structure used for libmemcached.
9 *
10 */
11
12 /*
13 This is a partial implementation for fetching/creating memcached_server_st objects.
14 */
15 #include "common.h"
16
17 static inline void _server_init(memcached_server_st *self, const memcached_st *root,
18 const char *hostname, in_port_t port,
19 uint32_t weight, memcached_connection_t type)
20 {
21 self->options.sockaddr_inited= false;
22 self->number_of_hosts= 0;
23 self->cursor_active= 0;
24 self->port= port;
25 self->cached_errno= 0;
26 self->fd= -1;
27 self->io_bytes_sent= 0;
28 self->server_failure_counter= 0;
29 self->weight= weight;
30 self->state.is_corked= false;
31 self->major_version= 0;
32 self->micro_version= 0;
33 self->minor_version= 0;
34 self->type= type;
35 self->read_ptr= self->read_buffer;
36 self->cached_server_error= NULL;
37 self->read_buffer_length= 0;
38 self->read_data_length= 0;
39 self->write_buffer_offset= 0;
40 self->address_info= NULL;
41
42 if (root)
43 {
44 self->next_retry= root->retry_timeout;
45 }
46 else
47 {
48 self->next_retry= 0;
49 }
50
51 self->root= root;
52 self->limit_maxbytes= 0;
53 strncpy(self->hostname, hostname, MEMCACHED_MAX_HOST_LENGTH - 1);
54 }
55
56 static memcached_server_st *_server_create(memcached_server_st *self, const memcached_st *memc)
57 {
58 if (self == NULL)
59 {
60 self= (memcached_server_st *)memc->call_malloc(memc, sizeof(memcached_server_st));
61
62 if (! self)
63 return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
64
65 self->options.is_allocated= true;
66 }
67 else
68 {
69 self->options.is_allocated= false;
70 }
71
72 self->options.is_initialized= true;
73
74 return self;
75 }
76
77 memcached_server_st *memcached_server_create_with(const memcached_st *memc, memcached_server_st *self,
78 const char *hostname, in_port_t port,
79 uint32_t weight, memcached_connection_t type)
80 {
81 self= _server_create(self, memc);
82
83 if (self == NULL)
84 return NULL;
85
86 _server_init(self, memc, hostname, port, weight, type);
87
88
89 if (type == MEMCACHED_CONNECTION_UDP)
90 {
91 self->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
92 memcached_io_init_udp_header(self, 0);
93 }
94
95 return self;
96 }
97
98 void memcached_server_free(memcached_server_st *self)
99 {
100 memcached_quit_server(self, 0);
101
102 if (self->cached_server_error)
103 free(self->cached_server_error);
104
105 if (self->address_info)
106 freeaddrinfo(self->address_info);
107
108 if (memcached_is_allocated(self))
109 {
110 self->root->call_free(self->root, self);
111 }
112 else
113 {
114 self->options.is_initialized= false;
115 }
116 }
117
118 /*
119 If we do not have a valid object to clone from, we toss an error.
120 */
121 memcached_server_st *memcached_server_clone(memcached_server_st *destination,
122 const memcached_server_st *source)
123 {
124 /* We just do a normal create if source is missing */
125 if (source == NULL)
126 return NULL;
127
128 destination= memcached_server_create_with(source->root, destination,
129 source->hostname, source->port, source->weight,
130 source->type);
131 if (destination != NULL)
132 {
133 destination->cached_errno= source->cached_errno;
134
135 if (source->cached_server_error)
136 destination->cached_server_error= strdup(source->cached_server_error);
137 }
138
139 return destination;
140
141 }
142
143 memcached_return_t memcached_server_cursor(memcached_st *ptr,
144 memcached_server_fn *callback,
145 void *context,
146 uint32_t number_of_callbacks)
147 {
148 uint32_t y;
149
150 for (y= 0; y < memcached_server_count(ptr); y++)
151 {
152 uint32_t x;
153 memcached_server_instance_st *instance=
154 memcached_server_instance_fetch(ptr, y);
155
156 for (x= 0; x < number_of_callbacks; x++)
157 {
158 unsigned int iferror;
159
160 iferror= (*callback[x])(ptr, instance, context);
161
162 if (iferror)
163 continue;
164 }
165 }
166
167 return MEMCACHED_SUCCESS;
168 }
169
170 memcached_server_st *memcached_server_by_key(memcached_st *ptr, const char *key, size_t key_length, memcached_return_t *error)
171 {
172 uint32_t server_key;
173 memcached_server_instance_st *instance;
174
175 *error= memcached_validate_key_length(key_length,
176 ptr->flags.binary_protocol);
177 unlikely (*error != MEMCACHED_SUCCESS)
178 return NULL;
179
180 unlikely (memcached_server_count(ptr) == 0)
181 {
182 *error= MEMCACHED_NO_SERVERS;
183 return NULL;
184 }
185
186 if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
187 {
188 *error= MEMCACHED_BAD_KEY_PROVIDED;
189 return NULL;
190 }
191
192 server_key= memcached_generate_hash(ptr, key, key_length);
193 instance= memcached_server_instance_fetch(ptr, server_key);
194
195 return memcached_server_clone(NULL, instance);
196
197 }
198
199 const char *memcached_server_error(memcached_server_st *ptr)
200 {
201 return ptr
202 ? ptr->cached_server_error
203 : NULL;
204 }
205
206 void memcached_server_error_reset(memcached_server_st *ptr)
207 {
208 ptr->cached_server_error[0]= 0;
209 }
210
211 memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr)
212 {
213 return ptr->last_disconnected_server;
214 }
215
216 uint32_t memcached_server_list_count(memcached_server_st *ptr)
217 {
218 return (ptr == NULL)
219 ? 0
220 : memcached_servers_count(ptr);
221 }
222
223 void memcached_server_list_free(memcached_server_st *ptr)
224 {
225 server_list_free(NULL, ptr);
226 }