Fix all warnings found via clang.
[awesomized/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 <cstdarg>
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(org::libmemcached::Instance& server, memcached_st& memc)
54 {
55 if (server.error_messages and server.error_messages->query_id != server.root->query_id)
56 {
57 memcached_error_free(server);
58 }
59
60 if (memc.error_messages == NULL)
61 {
62 return;
63 }
64
65 memcached_error_t *error= libmemcached_xmalloc(&memc, memcached_error_t);
66 if (error == NULL) // Bad business if this happens
67 {
68 return;
69 }
70
71 memcpy(error, memc.error_messages, sizeof(memcached_error_t));
72 error->next= server.error_messages;
73 server.error_messages= error;
74 }
75
76 #if 0
77 static int error_log_fd= -1;
78 #endif
79
80 static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
81 {
82 if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
83 {
84 memcached_error_free(memc);
85 }
86
87 // For memory allocation we use our error since it is a bit more specific
88 if (local_errno == ENOMEM and rc == MEMCACHED_ERRNO)
89 {
90 rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
91 }
92
93 if (rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
94 {
95 local_errno= ENOMEM;
96 }
97
98 if (rc == MEMCACHED_ERRNO and not local_errno)
99 {
100 local_errno= errno;
101 rc= MEMCACHED_ERRNO;
102 }
103
104 if (rc == MEMCACHED_ERRNO and local_errno == ENOTCONN)
105 {
106 rc= MEMCACHED_CONNECTION_FAILURE;
107 }
108
109 if (rc == MEMCACHED_ERRNO and local_errno == ECONNRESET)
110 {
111 rc= MEMCACHED_CONNECTION_FAILURE;
112 }
113
114 if (local_errno == EINVAL)
115 {
116 rc= MEMCACHED_INVALID_ARGUMENTS;
117 }
118
119 if (local_errno == ECONNREFUSED)
120 {
121 rc= MEMCACHED_CONNECTION_FAILURE;
122 }
123
124 memcached_error_t *error= libmemcached_xmalloc(&memc, memcached_error_t);
125 if (error == NULL) // Bad business if this happens
126 {
127 return;
128 }
129
130 error->root= &memc;
131 error->query_id= memc.query_id;
132 error->rc= rc;
133 error->local_errno= local_errno;
134
135 const char *errmsg_ptr;
136 char errmsg[MAX_ERROR_LENGTH];
137 errmsg[0]= 0;
138 errmsg_ptr= errmsg;
139
140 if (local_errno)
141 {
142 #ifdef STRERROR_R_CHAR_P
143 errmsg_ptr= strerror_r(local_errno, errmsg, sizeof(errmsg));
144 #else
145 strerror_r(local_errno, errmsg, sizeof(errmsg));
146 errmsg_ptr= errmsg;
147 #endif
148 }
149
150
151 if (str and str->size and local_errno)
152 {
153 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s(%s), %.*s -> %s",
154 long(error->root),
155 memcached_strerror(&memc, rc),
156 errmsg_ptr,
157 memcached_string_printf(*str), at);
158 }
159 else if (local_errno)
160 {
161 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s(%s) -> %s",
162 long(error->root),
163 memcached_strerror(&memc, rc),
164 errmsg_ptr,
165 at);
166 }
167 else if (rc == MEMCACHED_PARSE_ERROR and str and str->size)
168 {
169 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %.*s -> %s",
170 long(error->root),
171 int(str->size), str->c_str, at);
172 }
173 else if (str and str->size)
174 {
175 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s, %.*s -> %s",
176 long(error->root),
177 memcached_strerror(&memc, rc),
178 int(str->size), str->c_str, at);
179 }
180 else
181 {
182 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%lu) %s -> %s",
183 long(error->root),
184 memcached_strerror(&memc, rc), at);
185 }
186
187 error->next= memc.error_messages;
188 memc.error_messages= error;
189
190 #if 0
191 if (error_log_fd == -1)
192 {
193 // unlink("/tmp/libmemcachd.log");
194 if ((error_log_fd= open("/tmp/libmemcachd.log", O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)
195 {
196 perror("open");
197 error_log_fd= -1;
198 }
199 }
200 ::write(error_log_fd, error->message, error->size);
201 ::write(error_log_fd, "\n", 1);
202 #endif
203 }
204
205 memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, const char *str, size_t length)
206 {
207 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
208 memcached_string_t tmp= { str, length };
209 return memcached_set_error(memc, rc, at, tmp);
210 }
211
212 memcached_return_t memcached_set_error(org::libmemcached::Instance& self, memcached_return_t rc, const char *at, const char *str, size_t length)
213 {
214 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
215 assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a Instance");
216
217 memcached_string_t tmp= { str, length };
218 return memcached_set_error(self, rc, at, tmp);
219 }
220
221 #ifndef __INTEL_COMPILER
222 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
223 #endif
224
225 memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, memcached_string_t& str)
226 {
227 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
228 if (memcached_fatal(rc) == false)
229 {
230 return rc;
231 }
232
233 _set(memc, &str, rc, at);
234
235 return rc;
236 }
237
238 memcached_return_t memcached_set_parser_error(memcached_st& memc,
239 const char *at,
240 const char *format, ...)
241 {
242 va_list args;
243
244 char buffer[BUFSIZ];
245 va_start(args, format);
246 int length= vsnprintf(buffer, sizeof(buffer), format, args);
247 va_end(args);
248
249 return memcached_set_error(memc, MEMCACHED_PARSE_ERROR, at, buffer, length);
250 }
251
252 static inline size_t append_host_to_string(org::libmemcached::Instance& self, char* buffer, const size_t buffer_length)
253 {
254 size_t size= 0;
255 switch (self.type)
256 {
257 case MEMCACHED_CONNECTION_TCP:
258 case MEMCACHED_CONNECTION_UDP:
259 size+= snprintf(buffer, buffer_length, " host: %s:%d",
260 self.hostname, int(self.port()));
261 break;
262
263 case MEMCACHED_CONNECTION_UNIX_SOCKET:
264 size+= snprintf(buffer, buffer_length, " socket: %s",
265 self.hostname);
266 break;
267 }
268
269 return size;
270 }
271
272 memcached_return_t memcached_set_error(org::libmemcached::Instance& self, memcached_return_t rc, const char *at, memcached_string_t& str)
273 {
274 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
275 assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a org::libmemcached::Instance");
276 if (memcached_fatal(rc) == false)
277 {
278 return rc;
279 }
280
281 char hostname_port_message[MAX_ERROR_LENGTH];
282 char* hostname_port_message_ptr= hostname_port_message;
283 int size= 0;
284 if (str.size)
285 {
286 size= snprintf(hostname_port_message_ptr, sizeof(hostname_port_message), "%.*s, ",
287 memcached_string_printf(str));
288 hostname_port_message_ptr+= size;
289 }
290
291 size+= append_host_to_string(self, hostname_port_message_ptr, sizeof(hostname_port_message) -size);
292
293 memcached_string_t error_host= { hostname_port_message, size_t(size) };
294
295 assert(self.root);
296 if (self.root == NULL)
297 {
298 return rc;
299 }
300
301 _set(*self.root, &error_host, rc, at);
302 _set(self, (*self.root));
303 assert(self.root->error_messages);
304 assert(self.error_messages);
305
306 return rc;
307 }
308
309 memcached_return_t memcached_set_error(org::libmemcached::Instance& self, memcached_return_t rc, const char *at)
310 {
311 assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a org::libmemcached::Instance");
312 if (memcached_fatal(rc) == false)
313 {
314 return rc;
315 }
316
317 char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")];
318 size_t size= append_host_to_string(self, hostname_port, sizeof(hostname_port));
319
320 memcached_string_t error_host= { hostname_port, size};
321
322 if (self.root == NULL)
323 {
324 return rc;
325 }
326
327 _set(*self.root, &error_host, rc, at);
328 _set(self, *self.root);
329
330 return rc;
331 }
332
333 memcached_return_t memcached_set_error(memcached_st& self, memcached_return_t rc, const char *at)
334 {
335 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
336 if (memcached_fatal(rc) == false)
337 {
338 return rc;
339 }
340
341 _set(self, NULL, rc, at);
342
343 return rc;
344 }
345
346 memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at, const char *str, size_t length)
347 {
348 memcached_string_t tmp= { str, length };
349 return memcached_set_errno(self, local_errno, at, tmp);
350 }
351
352 memcached_return_t memcached_set_errno(org::libmemcached::Instance& self, int local_errno, const char *at, const char *str, size_t length)
353 {
354 memcached_string_t tmp= { str, length };
355 return memcached_set_errno(self, local_errno, at, tmp);
356 }
357
358 memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at)
359 {
360 if (local_errno == 0)
361 {
362 return MEMCACHED_SUCCESS;
363 }
364
365 memcached_return_t rc= MEMCACHED_ERRNO;
366 _set(self, NULL, rc, at, local_errno);
367
368 return rc;
369 }
370
371 memcached_return_t memcached_set_errno(memcached_st& memc, int local_errno, const char *at, memcached_string_t& str)
372 {
373 if (local_errno == 0)
374 {
375 return MEMCACHED_SUCCESS;
376 }
377
378 memcached_return_t rc= MEMCACHED_ERRNO;
379 _set(memc, &str, rc, at, local_errno);
380
381 return rc;
382 }
383
384 memcached_return_t memcached_set_errno(org::libmemcached::Instance& self, int local_errno, const char *at, memcached_string_t& str)
385 {
386 if (local_errno == 0)
387 {
388 return MEMCACHED_SUCCESS;
389 }
390
391 char hostname_port_message[MAX_ERROR_LENGTH];
392 char* hostname_port_message_ptr= hostname_port_message;
393 size_t size= 0;
394 if (str.size)
395 {
396 size= snprintf(hostname_port_message_ptr, sizeof(hostname_port_message), "%.*s, ", memcached_string_printf(str));
397 }
398 size+= append_host_to_string(self, hostname_port_message_ptr, sizeof(hostname_port_message) -size);
399
400 memcached_string_t error_host= { hostname_port_message, size };
401
402 memcached_return_t rc= MEMCACHED_ERRNO;
403 if (self.root == NULL)
404 {
405 return rc;
406 }
407
408 _set(*self.root, &error_host, rc, at, local_errno);
409 _set(self, (*self.root));
410
411 return rc;
412 }
413
414 memcached_return_t memcached_set_errno(org::libmemcached::Instance& self, int local_errno, const char *at)
415 {
416 if (local_errno == 0)
417 {
418 return MEMCACHED_SUCCESS;
419 }
420
421 char hostname_port_message[MAX_ERROR_LENGTH];
422 size_t size= append_host_to_string(self, hostname_port_message, sizeof(hostname_port_message));
423
424 memcached_string_t error_host= { hostname_port_message, size };
425
426 memcached_return_t rc= MEMCACHED_ERRNO;
427 if (self.root == NULL)
428 {
429 return rc;
430 }
431
432 _set(*self.root, &error_host, rc, at, local_errno);
433 _set(self, (*self.root));
434
435 return rc;
436 }
437
438 static void _error_print(const memcached_error_t *error)
439 {
440 if (error == NULL)
441 {
442 return;
443 }
444
445 if (error->size == 0)
446 {
447 fprintf(stderr, "\t%s\n", memcached_strerror(NULL, error->rc) );
448 }
449 else
450 {
451 fprintf(stderr, "\t%s %s\n", memcached_strerror(NULL, error->rc), error->message);
452 }
453
454 _error_print(error->next);
455 }
456
457 void memcached_error_print(const memcached_st *self)
458 {
459 if (self == NULL)
460 {
461 return;
462 }
463
464 _error_print(self->error_messages);
465
466 for (uint32_t x= 0; x < memcached_server_count(self); x++)
467 {
468 org::libmemcached::Instance* instance= memcached_instance_by_position(self, x);
469
470 _error_print(instance->error_messages);
471 }
472 }
473
474 static void _error_free(memcached_error_t *error)
475 {
476 if (error)
477 {
478 _error_free(error->next);
479
480 libmemcached_free(error->root, error);
481 }
482 }
483
484 void memcached_error_free(memcached_st& self)
485 {
486 _error_free(self.error_messages);
487 self.error_messages= NULL;
488 }
489
490 void memcached_error_free(org::libmemcached::Instance& self)
491 {
492 _error_free(self.error_messages);
493 self.error_messages= NULL;
494 }
495
496 void memcached_error_free(memcached_server_st& self)
497 {
498 _error_free(self.error_messages);
499 self.error_messages= NULL;
500 }
501
502 const char *memcached_error(const memcached_st *memc)
503 {
504 return memcached_last_error_message(memc);
505 }
506
507 const char *memcached_last_error_message(const memcached_st *memc)
508 {
509 if (memc)
510 {
511 if (memc->error_messages)
512 {
513 if (memc->error_messages->size == 0)
514 {
515 return memc->error_messages->message;
516 }
517
518 return memcached_strerror(memc, memc->error_messages->rc);
519 }
520
521 return memcached_strerror(memc, MEMCACHED_SUCCESS);
522 }
523
524 return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
525 }
526
527 bool memcached_has_current_error(memcached_st &memc)
528 {
529 if (memc.error_messages
530 and memc.error_messages->query_id == memc.query_id
531 and memcached_failed(memc.error_messages->rc))
532 {
533 return true;
534 }
535
536 return false;
537 }
538
539 bool memcached_has_current_error(org::libmemcached::Instance& server)
540 {
541 return memcached_has_current_error(*(server.root));
542 }
543
544 memcached_return_t memcached_last_error(const memcached_st *memc)
545 {
546 if (memc)
547 {
548 if (memc->error_messages)
549 {
550 return memc->error_messages->rc;
551 }
552
553 return MEMCACHED_SUCCESS;
554 }
555
556 return MEMCACHED_INVALID_ARGUMENTS;
557 }
558
559 int memcached_last_error_errno(const memcached_st *memc)
560 {
561 if (memc == NULL)
562 {
563 return 0;
564 }
565
566 if (memc->error_messages == NULL)
567 {
568 return 0;
569 }
570
571 return memc->error_messages->local_errno;
572 }
573
574 const char *memcached_server_error(const memcached_server_instance_st server)
575 {
576 if (server == NULL)
577 {
578 return NULL;
579 }
580
581 if (server->error_messages == NULL)
582 {
583 return memcached_strerror(server->root, MEMCACHED_SUCCESS);
584 }
585
586 if (server->error_messages->size == 0)
587 {
588 return memcached_strerror(server->root, server->error_messages->rc);
589 }
590
591 return server->error_messages->message;
592 }
593
594
595 memcached_error_t *memcached_error_copy(const org::libmemcached::Instance& server)
596 {
597 if (server.error_messages == NULL)
598 {
599 return NULL;
600 }
601
602 memcached_error_t *error= libmemcached_xmalloc(server.root, memcached_error_t);
603 memcpy(error, server.error_messages, sizeof(memcached_error_t));
604 error->next= NULL;
605
606 return error;
607 }
608
609 memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr)
610 {
611 if (ptr == NULL)
612 {
613 return MEMCACHED_INVALID_ARGUMENTS;
614 }
615
616 if (ptr and ptr->error_messages)
617 {
618 return ptr->error_messages->rc;
619 }
620
621 return MEMCACHED_SUCCESS;
622 }
623
624 memcached_return_t memcached_instance_error_return(org::libmemcached::Instance* instance)
625 {
626 if (instance == NULL)
627 {
628 return MEMCACHED_INVALID_ARGUMENTS;
629 }
630
631 if (instance and instance->error_messages)
632 {
633 return instance->error_messages->rc;
634 }
635
636 return MEMCACHED_SUCCESS;
637 }