Updating to latest libtest.
[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 #include <cassert>
40
41 #define MAX_ERROR_LENGTH 2048
42 struct memcached_error_t
43 {
44 memcached_st *root;
45 uint64_t query_id;
46 struct memcached_error_t *next;
47 memcached_return_t rc;
48 int local_errno;
49 size_t size;
50 char message[MAX_ERROR_LENGTH];
51 };
52
53 static void _set(memcached_server_st& server, memcached_st& memc)
54 {
55 if (server.error_messages && server.error_messages->query_id != server.root->query_id)
56 {
57 memcached_error_free(server);
58 }
59
60 if (memc.error_messages == NULL)
61 return;
62
63 memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
64 if (not error) // Bad business if this happens
65 return;
66
67 memcpy(error, memc.error_messages, sizeof(memcached_error_t));
68 error->next= server.error_messages;
69 server.error_messages= error;
70 }
71
72 static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
73 {
74 (void)at;
75 if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
76 {
77 memcached_error_free(memc);
78 }
79
80 // For memory allocation we use our error since it is a bit more specific
81 if (local_errno == ENOMEM and rc == MEMCACHED_ERRNO)
82 {
83 rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
84 }
85
86 if (rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
87 {
88 local_errno= ENOMEM;
89 }
90
91 if (rc == MEMCACHED_ERRNO and not local_errno)
92 {
93 local_errno= errno;
94 rc= MEMCACHED_ERRNO;
95 }
96
97 if (rc == MEMCACHED_ERRNO and local_errno == ENOTCONN)
98 {
99 rc= MEMCACHED_CONNECTION_FAILURE;
100 }
101
102 if (local_errno == EINVAL)
103 {
104 rc= MEMCACHED_INVALID_ARGUMENTS;
105 }
106
107 if (local_errno == ECONNREFUSED)
108 {
109 rc= MEMCACHED_CONNECTION_FAILURE;
110 }
111
112 memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
113 if (not error) // Bad business if this happens
114 return;
115
116 error->root= &memc;
117 error->query_id= memc.query_id;
118 error->rc= rc;
119 error->local_errno= local_errno;
120
121 const char *errmsg_ptr;
122 char errmsg[MAX_ERROR_LENGTH];
123 errmsg[0]= 0;
124 errmsg_ptr= errmsg;
125
126 if (local_errno)
127 {
128 #ifdef STRERROR_R_CHAR_P
129 errmsg_ptr= strerror_r(local_errno, errmsg, sizeof(errmsg));
130 #else
131 strerror_r(local_errno, errmsg, sizeof(errmsg));
132 errmsg_ptr= errmsg;
133 #endif
134 }
135
136
137 if (str and str->size and local_errno)
138 {
139 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s), %.*s -> %s",
140 memcached_strerror(&memc, rc),
141 errmsg_ptr,
142 memcached_string_printf(*str), at);
143 }
144 else if (local_errno)
145 {
146 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s) -> %s",
147 memcached_strerror(&memc, rc),
148 errmsg_ptr,
149 at);
150 }
151 else if (str and str->size)
152 {
153 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s, %.*s -> %s",
154 memcached_strerror(&memc, rc),
155 int(str->size), str->c_str, at);
156 }
157 else
158 {
159 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s -> %s",
160 memcached_strerror(&memc, rc), at);
161 }
162
163 error->next= memc.error_messages;
164 memc.error_messages= error;
165 }
166
167 memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, const char *str, size_t length)
168 {
169 assert(rc != MEMCACHED_ERRNO);
170 memcached_string_t tmp= { str, length };
171 return memcached_set_error(memc, rc, at, tmp);
172 }
173
174 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at, const char *str, size_t length)
175 {
176 assert(rc != MEMCACHED_ERRNO);
177 assert(rc != MEMCACHED_SOME_ERRORS);
178 memcached_string_t tmp= { str, length };
179 return memcached_set_error(self, rc, at, tmp);
180 }
181
182 memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, memcached_string_t& str)
183 {
184 assert(rc != MEMCACHED_ERRNO);
185 if (memcached_success(rc))
186 return MEMCACHED_SUCCESS;
187
188 _set(memc, &str, rc, at);
189
190 return rc;
191 }
192
193 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at, memcached_string_t& str)
194 {
195 assert(rc != MEMCACHED_ERRNO);
196 assert(rc != MEMCACHED_SOME_ERRORS);
197 if (memcached_success(rc))
198 return MEMCACHED_SUCCESS;
199
200 char hostname_port_message[MAX_ERROR_LENGTH];
201 int size;
202 if (str.size)
203 {
204 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d",
205 memcached_string_printf(str),
206 self.hostname, int(self.port));
207 }
208 else
209 {
210 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
211 self.hostname, int(self.port));
212 }
213
214 memcached_string_t error_host= { hostname_port_message, size };
215
216 if (not self.root)
217 return rc;
218
219 _set(*self.root, &error_host, rc, at);
220 _set(self, (*self.root));
221
222 return rc;
223 }
224
225 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at)
226 {
227 assert(rc != MEMCACHED_ERRNO);
228 assert(rc != MEMCACHED_SOME_ERRORS);
229 if (memcached_success(rc))
230 return MEMCACHED_SUCCESS;
231
232 char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")];
233 int size= snprintf(hostname_port, sizeof(hostname_port), "host: %s:%d", self.hostname, int(self.port));
234
235 memcached_string_t error_host= { hostname_port, size};
236
237 if (not self.root)
238 return rc;
239
240 _set(*self.root, &error_host, rc, at);
241 _set(self, *self.root);
242
243 return rc;
244 }
245
246 memcached_return_t memcached_set_error(memcached_st& self, memcached_return_t rc, const char *at)
247 {
248 assert(rc != MEMCACHED_ERRNO);
249 if (memcached_success(rc))
250 return MEMCACHED_SUCCESS;
251
252 _set(self, NULL, rc, at);
253
254 return rc;
255 }
256
257 memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at, const char *str, size_t length)
258 {
259 memcached_string_t tmp= { str, length };
260 return memcached_set_errno(self, local_errno, at, tmp);
261 }
262
263 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at, const char *str, size_t length)
264 {
265 memcached_string_t tmp= { str, length };
266 return memcached_set_errno(self, local_errno, at, tmp);
267 }
268
269 memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at)
270 {
271 if (not local_errno)
272 return MEMCACHED_SUCCESS;
273
274 memcached_return_t rc= MEMCACHED_ERRNO;
275 _set(self, NULL, rc, at, local_errno);
276
277 return rc;
278 }
279
280 memcached_return_t memcached_set_errno(memcached_st& memc, int local_errno, const char *at, memcached_string_t& str)
281 {
282 if (not local_errno)
283 return MEMCACHED_SUCCESS;
284
285 memcached_return_t rc= MEMCACHED_ERRNO;
286 _set(memc, &str, rc, at, local_errno);
287
288 return rc;
289 }
290
291 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at, memcached_string_t& str)
292 {
293 if (not local_errno)
294 return MEMCACHED_SUCCESS;
295
296 char hostname_port_message[MAX_ERROR_LENGTH];
297 int size;
298 if (str.size)
299 {
300 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d",
301 memcached_string_printf(str),
302 self.hostname, int(self.port));
303 }
304 else
305 {
306 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
307 self.hostname, int(self.port));
308 }
309
310 memcached_string_t error_host= { hostname_port_message, size };
311
312 memcached_return_t rc= MEMCACHED_ERRNO;
313 if (not self.root)
314 return rc;
315
316 _set(*self.root, &error_host, rc, at, local_errno);
317 _set(self, (*self.root));
318
319 return rc;
320 }
321
322 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at)
323 {
324 if (not local_errno)
325 return MEMCACHED_SUCCESS;
326
327 char hostname_port_message[MAX_ERROR_LENGTH];
328 int size = snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
329 self.hostname, int(self.port));
330
331 memcached_string_t error_host= { hostname_port_message, size };
332
333 memcached_return_t rc= MEMCACHED_ERRNO;
334 if (not self.root)
335 return rc;
336
337 _set(*self.root, &error_host, rc, at, local_errno);
338 _set(self, (*self.root));
339
340 return rc;
341 }
342
343 static void _error_print(const memcached_error_t *error)
344 {
345 if (not error)
346 return;
347
348 if (not error->size)
349 {
350 fprintf(stderr, "%s\n", memcached_strerror(NULL, error->rc) );
351 }
352 else
353 {
354 fprintf(stderr, "%s %s\n", memcached_strerror(NULL, error->rc), error->message);
355 }
356
357 _error_print(error->next);
358 }
359
360 void memcached_error_print(const memcached_st *self)
361 {
362 if (not self)
363 return;
364
365 _error_print(self->error_messages);
366 }
367
368 static void _error_free(memcached_error_t *error)
369 {
370 if (not error)
371 return;
372
373 _error_free(error->next);
374
375 if (error && error->root)
376 {
377 libmemcached_free(error->root, error);
378 }
379 else if (error)
380 {
381 free(error);
382 }
383 }
384
385 void memcached_error_free(memcached_st& self)
386 {
387 _error_free(self.error_messages);
388 self.error_messages= NULL;
389 }
390
391 void memcached_error_free(memcached_server_st& self)
392 {
393 _error_free(self.error_messages);
394 self.error_messages= NULL;
395 }
396
397 const char *memcached_last_error_message(memcached_st *memc)
398 {
399 if (not memc)
400 return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
401
402 if (not memc->error_messages)
403 return memcached_strerror(memc, MEMCACHED_SUCCESS);
404
405 if (not memc->error_messages->size)
406 return memcached_strerror(memc, memc->error_messages->rc);
407
408 return memc->error_messages->message;
409 }
410
411
412 bool memcached_has_current_error(memcached_st &memc)
413 {
414 if (memc.error_messages
415 and memc.error_messages->query_id == memc.query_id
416 and memcached_failed(memc.error_messages->rc))
417 {
418 return true;
419 }
420
421 return false;
422 }
423
424 memcached_return_t memcached_last_error(memcached_st *memc)
425 {
426 if (not memc)
427 return MEMCACHED_INVALID_ARGUMENTS;
428
429 if (not memc->error_messages)
430 return MEMCACHED_SUCCESS;
431
432 return memc->error_messages->rc;
433 }
434
435 int memcached_last_error_errno(memcached_st *memc)
436 {
437 if (not memc)
438 return 0;
439
440 if (not memc->error_messages)
441 return 0;
442
443 return memc->error_messages->local_errno;
444 }
445
446 const char *memcached_server_error(memcached_server_instance_st server)
447 {
448 if (not server)
449 return memcached_strerror(server->root, MEMCACHED_INVALID_ARGUMENTS);
450
451 if (not server->error_messages)
452 return memcached_strerror(server->root, MEMCACHED_SUCCESS);
453
454 if (not server->error_messages->size)
455 return memcached_strerror(server->root, server->error_messages->rc);
456
457 return server->error_messages->message;
458 }
459
460
461 memcached_error_t *memcached_error_copy(const memcached_server_st& server)
462 {
463 if (not server.error_messages)
464 return NULL;
465
466 memcached_error_t *error= (memcached_error_t *)libmemcached_malloc(server.root, sizeof(memcached_error_t));
467 memcpy(error, server.error_messages, sizeof(memcached_error_t));
468 error->next= NULL;
469
470 return error;
471 }
472
473 memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr)
474 {
475 if (ptr and ptr->error_messages)
476 {
477 return ptr->error_messages->rc;
478 }
479
480 return MEMCACHED_FAILURE;
481 }