Merge Thomason's cork patch.
[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 memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr)
18 {
19 if (ptr == NULL)
20 {
21 ptr= (memcached_server_st *)memc->call_calloc(memc, 1, sizeof(memcached_server_st));
22
23 if (!ptr)
24 return NULL; /* MEMCACHED_MEMORY_ALLOCATION_FAILURE */
25
26 ptr->options.is_allocated= true;
27 }
28 else
29 {
30 memset(ptr, 0, sizeof(memcached_server_st));
31 }
32
33 ptr->root= memc;
34
35 return ptr;
36 }
37
38 memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host,
39 const char *hostname, in_port_t port,
40 uint32_t weight, memcached_connection_t type)
41 {
42 host= memcached_server_create(memc, host);
43
44 if (host == NULL)
45 return NULL;
46
47 strncpy(host->hostname, hostname, MEMCACHED_MAX_HOST_LENGTH - 1);
48 host->root= memc ? memc : NULL;
49 host->port= port;
50 host->weight= weight;
51 host->fd= -1;
52 host->type= type;
53 host->read_ptr= host->read_buffer;
54 host->state.is_corked= 0;
55 if (memc)
56 host->next_retry= memc->retry_timeout;
57 if (type == MEMCACHED_CONNECTION_UDP)
58 {
59 host->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
60 memcached_io_init_udp_header(host, 0);
61 }
62
63 return host;
64 }
65
66 void memcached_server_free(memcached_server_st *ptr)
67 {
68 memcached_quit_server(ptr, 0);
69
70 if (ptr->cached_server_error)
71 free(ptr->cached_server_error);
72
73 if (ptr->address_info)
74 freeaddrinfo(ptr->address_info);
75
76
77 if (memcached_is_allocated(ptr))
78 {
79 ptr->root->call_free(ptr->root, ptr);
80 }
81 else
82 {
83 memset(ptr, 0, sizeof(memcached_server_st));
84 }
85 }
86
87 /*
88 If we do not have a valid object to clone from, we toss an error.
89 */
90 memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcached_server_st *ptr)
91 {
92 memcached_server_st *rv= NULL;
93
94 /* We just do a normal create if ptr is missing */
95 if (ptr == NULL)
96 return NULL;
97
98 rv= memcached_server_create_with(ptr->root, clone,
99 ptr->hostname, ptr->port, ptr->weight,
100 ptr->type);
101 if (rv != NULL)
102 {
103 rv->cached_errno= ptr->cached_errno;
104 if (ptr->cached_server_error)
105 rv->cached_server_error= strdup(ptr->cached_server_error);
106 }
107
108 return rv;
109
110 }
111
112 memcached_return_t memcached_server_cursor(memcached_st *ptr,
113 memcached_server_fn *callback,
114 void *context,
115 uint32_t number_of_callbacks)
116 {
117 uint32_t y;
118
119 for (y= 0; y < memcached_server_count(ptr); y++)
120 {
121 uint32_t x;
122 memcached_server_instance_st *instance=
123 memcached_server_instance_fetch(ptr, y);
124
125 for (x= 0; x < number_of_callbacks; x++)
126 {
127 unsigned int iferror;
128
129 iferror= (*callback[x])(ptr, instance, context);
130
131 if (iferror)
132 continue;
133 }
134 }
135
136 return MEMCACHED_SUCCESS;
137 }
138
139 memcached_server_st *memcached_server_by_key(memcached_st *ptr, const char *key, size_t key_length, memcached_return_t *error)
140 {
141 uint32_t server_key;
142 memcached_server_instance_st *instance;
143
144 *error= memcached_validate_key_length(key_length,
145 ptr->flags.binary_protocol);
146 unlikely (*error != MEMCACHED_SUCCESS)
147 return NULL;
148
149 unlikely (memcached_server_count(ptr) == 0)
150 {
151 *error= MEMCACHED_NO_SERVERS;
152 return NULL;
153 }
154
155 if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
156 {
157 *error= MEMCACHED_BAD_KEY_PROVIDED;
158 return NULL;
159 }
160
161 server_key= memcached_generate_hash(ptr, key, key_length);
162 instance= memcached_server_instance_fetch(ptr, server_key);
163
164 return memcached_server_clone(NULL, instance);
165
166 }
167
168 const char *memcached_server_error(memcached_server_st *ptr)
169 {
170 return ptr
171 ? ptr->cached_server_error
172 : NULL;
173 }
174
175 void memcached_server_error_reset(memcached_server_st *ptr)
176 {
177 ptr->cached_server_error[0]= 0;
178 }
179
180 memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr)
181 {
182 return ptr->last_disconnected_server;
183 }
184
185 uint32_t memcached_server_list_count(memcached_server_st *ptr)
186 {
187 return (ptr == NULL)
188 ? 0
189 : memcached_servers_count(ptr);
190 }
191
192 void memcached_server_list_free(memcached_server_st *ptr)
193 {
194 server_list_free(NULL, ptr);
195 }