Update basic string.
[m6w6/libmemcached] / libmemcached / error.cc
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * LibMemcached
4 *
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following disclaimer
17 * in the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * * The names of its contributors may not be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37
38 #include "libmemcached/common.h"
39
40 #define MAX_ERROR_LENGTH 2048
41 struct memcached_error_t
42 {
43 memcached_st *root;
44 uint64_t query_id;
45 struct memcached_error_t *next;
46 memcached_return_t rc;
47 int local_errno;
48 size_t size;
49 char message[MAX_ERROR_LENGTH];
50 };
51
52 static void _set(memcached_st *memc, memcached_string_t *str, memcached_return_t &rc, int local_errno= 0)
53 {
54 WATCHPOINT_ASSERT(memc);
55 if (not memc)
56 return;
57
58 if (memc->error_messages && memc->error_messages->query_id != memc->query_id)
59 {
60 memcached_error_free(memc);
61 }
62
63 if (rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE or rc == MEMCACHED_ERRNO)
64 {
65 local_errno= errno;
66 rc= MEMCACHED_ERRNO;
67 }
68
69 memcached_error_t *error;
70 error= (struct memcached_error_t *)libmemcached_malloc(memc, sizeof(struct memcached_error_t));
71
72 if (not error)
73 return;
74
75 error->root= memc;
76 error->query_id= memc->query_id;
77 error->rc= rc;
78 error->local_errno= local_errno;
79
80 if (str)
81 {
82 size_t length= str->size > (size_t)MAX_ERROR_LENGTH ? MAX_ERROR_LENGTH : str->size;
83 error->size= length;
84 memcpy(error->message, str->c_str, error->size);
85 error->message[error->size]= 0;
86 }
87 else
88 {
89 error->size= 0;
90 }
91
92 error->next= memc->error_messages;
93 memc->error_messages= error;
94 }
95
96 memcached_return_t memcached_set_error_string(memcached_st *memc, memcached_return_t rc, const char *str, size_t length)
97 {
98 memcached_string_t tmp;
99 tmp.c_str= str;
100 tmp.size= length;
101 return memcached_set_error_message(memc, rc, &tmp);
102 }
103
104 memcached_return_t memcached_set_error_string(memcached_server_st& self, memcached_return_t rc, const char *str, size_t length)
105 {
106 memcached_string_t tmp;
107 tmp.c_str= str;
108 tmp.size= length;
109 return memcached_set_error_message(self, rc, &tmp);
110 }
111
112 memcached_return_t memcached_set_error_message(memcached_st *memc, memcached_return_t rc, memcached_string_t *str)
113 {
114 if (memcached_success(rc))
115 return MEMCACHED_SUCCESS;
116
117 _set(memc, str, rc);
118
119 return rc;
120 }
121
122 memcached_return_t memcached_set_error_message(memcached_server_st& self, memcached_return_t rc, memcached_string_t *str)
123 {
124 if (memcached_success(rc))
125 return MEMCACHED_SUCCESS;
126
127 char hostname_port_message[MAX_ERROR_LENGTH];
128 int size;
129 if (str and str->size)
130 {
131 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d",
132 memcached_string_printf(*str),
133 self.hostname, int(self.port));
134 }
135 else
136 {
137 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
138 self.hostname, int(self.port));
139 }
140
141 memcached_string_t error_host= { hostname_port_message, size };
142
143 _set((memcached_st*)self.root, &error_host, rc);
144
145 return rc;
146 }
147
148 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc)
149 {
150 if (memcached_success(rc))
151 return MEMCACHED_SUCCESS;
152
153 char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")];
154 int size= snprintf(hostname_port, sizeof(hostname_port), "host: %s:%d", self.hostname, int(self.port));
155
156 memcached_string_t error_host= { hostname_port, size};
157
158 _set((memcached_st*)self.root, &error_host, rc);
159
160 return rc;
161 }
162
163 memcached_return_t memcached_set_error(memcached_st* self, memcached_return_t rc)
164 {
165 if (memcached_success(rc))
166 return MEMCACHED_SUCCESS;
167
168 _set(self, NULL, rc);
169
170 return rc;
171 }
172
173 memcached_return_t memcached_set_error(memcached_st& self, memcached_return_t rc)
174 {
175 if (memcached_success(rc))
176 return MEMCACHED_SUCCESS;
177
178 _set(&self, NULL, rc);
179
180 return rc;
181 }
182
183 memcached_return_t memcached_set_errno(memcached_st *memc, int local_errno, memcached_string_t *str)
184 {
185 memcached_return_t rc= MEMCACHED_ERRNO;
186 _set(memc, str, rc, local_errno);
187
188 return rc;
189 }
190
191 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, memcached_string_t *str)
192 {
193 char hostname_port_message[MAX_ERROR_LENGTH];
194 int size;
195 if (str and str->size)
196 {
197 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d",
198 memcached_string_printf(*str),
199 self.hostname, int(self.port));
200 }
201 else
202 {
203 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
204 self.hostname, int(self.port));
205 }
206
207 memcached_string_t error_host= { hostname_port_message, size };
208
209 self.cached_errno= local_errno; // Store in the actual server
210 memcached_return_t rc= MEMCACHED_ERRNO;
211 _set((memcached_st*)self.root, &error_host, rc, local_errno);
212
213 return rc;
214 }
215
216 static void _error_print(const memcached_error_t *error)
217 {
218 if (not error)
219 return;
220
221 if (not error->size)
222 {
223 fprintf(stderr, "%s\n", memcached_strerror(NULL, error->rc) );
224 }
225 else
226 {
227 fprintf(stderr, "%s %s\n", memcached_strerror(NULL, error->rc), error->message);
228 }
229
230 _error_print(error->next);
231 }
232
233 void memcached_error_print(const memcached_st *self)
234 {
235 if (not self)
236 return;
237
238 _error_print(self->error_messages);
239 }
240
241 static void _error_free(memcached_error_t *error)
242 {
243 if (not error)
244 return;
245
246 _error_free(error->next);
247
248 if (error && error->root)
249 {
250 libmemcached_free(error->root, error);
251 }
252 else if (error)
253 {
254 free(error);
255 }
256 }
257
258 void memcached_error_free(memcached_st *self)
259 {
260 if (not self)
261 return;
262
263 _error_free(self->error_messages);
264 self->error_messages= NULL;
265 }
266
267 const char *memcached_last_error_message(memcached_st *memc)
268 {
269 if (not memc)
270 return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
271
272 if (not memc->error_messages)
273 return memcached_strerror(memc, MEMCACHED_SUCCESS);
274
275 if (not memc->error_messages->size)
276 return memcached_strerror(memc, memc->error_messages->rc);
277
278 return memc->error_messages->message;
279 }
280
281 memcached_return_t memcached_last_error(memcached_st *memc)
282 {
283 if (not memc)
284 return MEMCACHED_INVALID_ARGUMENTS;
285
286 if (not memc->error_messages)
287 return MEMCACHED_SUCCESS;
288
289 return memc->error_messages->rc;
290 }
291
292 int memcached_last_error_errno(memcached_st *memc)
293 {
294 if (not memc)
295 return 0;
296
297 if (not memc->error_messages)
298 return 0;
299
300 return memc->error_messages->local_errno;
301 }