Issues fixed for 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(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 (rc == MEMCACHED_PARSE_ERROR and str and str->size)
152 {
153 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%.*s -> %s",
154 int(str->size), str->c_str, at);
155 }
156 else if (str and str->size)
157 {
158 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s, %.*s -> %s",
159 memcached_strerror(&memc, rc),
160 int(str->size), str->c_str, at);
161 }
162 else
163 {
164 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s -> %s",
165 memcached_strerror(&memc, rc), at);
166 }
167
168 error->next= memc.error_messages;
169 memc.error_messages= error;
170 }
171
172 memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, const char *str, size_t length)
173 {
174 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
175 memcached_string_t tmp= { str, length };
176 return memcached_set_error(memc, rc, at, tmp);
177 }
178
179 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at, const char *str, size_t length)
180 {
181 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
182 assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
183 memcached_string_t tmp= { str, length };
184 return memcached_set_error(self, rc, at, tmp);
185 }
186
187 memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, memcached_string_t& str)
188 {
189 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
190 if (memcached_success(rc))
191 return MEMCACHED_SUCCESS;
192
193 _set(memc, &str, rc, at);
194
195 return rc;
196 }
197
198 memcached_return_t memcached_set_parser_error(memcached_st& memc,
199 const char *at,
200 const char *format, ...)
201 {
202 va_list args;
203
204 char buffer[BUFSIZ];
205 va_start(args, format);
206 int length= vsnprintf(buffer, sizeof(buffer), format, args);
207 va_end(args);
208
209 return memcached_set_error(memc, MEMCACHED_PARSE_ERROR, at, buffer, length);
210 }
211
212 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at, memcached_string_t& str)
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 memcached_server_st");
216 if (memcached_success(rc))
217 return MEMCACHED_SUCCESS;
218
219 char hostname_port_message[MAX_ERROR_LENGTH];
220 int size;
221 if (str.size)
222 {
223 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d",
224 memcached_string_printf(str),
225 self.hostname, int(self.port));
226 }
227 else
228 {
229 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
230 self.hostname, int(self.port));
231 }
232
233 memcached_string_t error_host= { hostname_port_message, size };
234
235 if (not self.root)
236 return rc;
237
238 _set(*self.root, &error_host, rc, at);
239 _set(self, (*self.root));
240
241 return rc;
242 }
243
244 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at)
245 {
246 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
247 assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
248 if (memcached_success(rc))
249 return MEMCACHED_SUCCESS;
250
251 char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")];
252 int size= snprintf(hostname_port, sizeof(hostname_port), "host: %s:%d", self.hostname, int(self.port));
253
254 memcached_string_t error_host= { hostname_port, size};
255
256 if (not self.root)
257 return rc;
258
259 _set(*self.root, &error_host, rc, at);
260 _set(self, *self.root);
261
262 return rc;
263 }
264
265 memcached_return_t memcached_set_error(memcached_st& self, memcached_return_t rc, const char *at)
266 {
267 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
268 if (memcached_success(rc))
269 return MEMCACHED_SUCCESS;
270
271 _set(self, NULL, rc, at);
272
273 return rc;
274 }
275
276 memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at, const char *str, size_t length)
277 {
278 memcached_string_t tmp= { str, length };
279 return memcached_set_errno(self, local_errno, at, tmp);
280 }
281
282 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at, const char *str, size_t length)
283 {
284 memcached_string_t tmp= { str, length };
285 return memcached_set_errno(self, local_errno, at, tmp);
286 }
287
288 memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at)
289 {
290 if (not local_errno)
291 return MEMCACHED_SUCCESS;
292
293 memcached_return_t rc= MEMCACHED_ERRNO;
294 _set(self, NULL, rc, at, local_errno);
295
296 return rc;
297 }
298
299 memcached_return_t memcached_set_errno(memcached_st& memc, int local_errno, const char *at, memcached_string_t& str)
300 {
301 if (not local_errno)
302 return MEMCACHED_SUCCESS;
303
304 memcached_return_t rc= MEMCACHED_ERRNO;
305 _set(memc, &str, rc, at, local_errno);
306
307 return rc;
308 }
309
310 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at, memcached_string_t& str)
311 {
312 if (not local_errno)
313 return MEMCACHED_SUCCESS;
314
315 char hostname_port_message[MAX_ERROR_LENGTH];
316 int size;
317 if (str.size)
318 {
319 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d",
320 memcached_string_printf(str),
321 self.hostname, int(self.port));
322 }
323 else
324 {
325 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
326 self.hostname, int(self.port));
327 }
328
329 memcached_string_t error_host= { hostname_port_message, size };
330
331 memcached_return_t rc= MEMCACHED_ERRNO;
332 if (not self.root)
333 return rc;
334
335 _set(*self.root, &error_host, rc, at, local_errno);
336 _set(self, (*self.root));
337
338 return rc;
339 }
340
341 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at)
342 {
343 if (not local_errno)
344 return MEMCACHED_SUCCESS;
345
346 char hostname_port_message[MAX_ERROR_LENGTH];
347 int size = snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
348 self.hostname, int(self.port));
349
350 memcached_string_t error_host= { hostname_port_message, size };
351
352 memcached_return_t rc= MEMCACHED_ERRNO;
353 if (not self.root)
354 return rc;
355
356 _set(*self.root, &error_host, rc, at, local_errno);
357 _set(self, (*self.root));
358
359 return rc;
360 }
361
362 static void _error_print(const memcached_error_t *error)
363 {
364 if (not error)
365 return;
366
367 if (not error->size)
368 {
369 fprintf(stderr, "%s\n", memcached_strerror(NULL, error->rc) );
370 }
371 else
372 {
373 fprintf(stderr, "%s %s\n", memcached_strerror(NULL, error->rc), error->message);
374 }
375
376 _error_print(error->next);
377 }
378
379 void memcached_error_print(const memcached_st *self)
380 {
381 if (not self)
382 return;
383
384 _error_print(self->error_messages);
385 }
386
387 static void _error_free(memcached_error_t *error)
388 {
389 if (not error)
390 return;
391
392 _error_free(error->next);
393
394 if (error && error->root)
395 {
396 libmemcached_free(error->root, error);
397 }
398 else if (error)
399 {
400 free(error);
401 }
402 }
403
404 void memcached_error_free(memcached_st& self)
405 {
406 _error_free(self.error_messages);
407 self.error_messages= NULL;
408 }
409
410 void memcached_error_free(memcached_server_st& self)
411 {
412 _error_free(self.error_messages);
413 self.error_messages= NULL;
414 }
415
416 const char *memcached_last_error_message(memcached_st *memc)
417 {
418 if (memc == NULL)
419 {
420 return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
421 }
422
423 if (not memc->error_messages)
424 return memcached_strerror(memc, MEMCACHED_SUCCESS);
425
426 if (not memc->error_messages->size)
427 return memcached_strerror(memc, memc->error_messages->rc);
428
429 return memc->error_messages->message;
430 }
431
432 bool memcached_has_current_error(memcached_st &memc)
433 {
434 if (memc.error_messages
435 and memc.error_messages->query_id == memc.query_id
436 and memcached_failed(memc.error_messages->rc))
437 {
438 return true;
439 }
440
441 return false;
442 }
443
444 bool memcached_has_current_error(memcached_server_st& server)
445 {
446 return memcached_has_current_error(*(server.root));
447 }
448
449 memcached_return_t memcached_last_error(memcached_st *memc)
450 {
451 if (memc == NULL)
452 {
453 return MEMCACHED_INVALID_ARGUMENTS;
454 }
455
456 if (not memc->error_messages)
457 return MEMCACHED_SUCCESS;
458
459 return memc->error_messages->rc;
460 }
461
462 int memcached_last_error_errno(memcached_st *memc)
463 {
464 if (memc == NULL)
465 {
466 return 0;
467 }
468
469 if (not memc->error_messages)
470 {
471 return 0;
472 }
473
474 return memc->error_messages->local_errno;
475 }
476
477 const char *memcached_server_error(memcached_server_instance_st server)
478 {
479 if (server == NULL)
480 {
481 return NULL;
482 }
483
484 if (not server->error_messages)
485 return memcached_strerror(server->root, MEMCACHED_SUCCESS);
486
487 if (not server->error_messages->size)
488 return memcached_strerror(server->root, server->error_messages->rc);
489
490 return server->error_messages->message;
491 }
492
493
494 memcached_error_t *memcached_error_copy(const memcached_server_st& server)
495 {
496 if (server.error_messages == NULL)
497 {
498 return NULL;
499 }
500
501 memcached_error_t *error= (memcached_error_t *)libmemcached_malloc(server.root, sizeof(memcached_error_t));
502 memcpy(error, server.error_messages, sizeof(memcached_error_t));
503 error->next= NULL;
504
505 return error;
506 }
507
508 memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr)
509 {
510 if (ptr == NULL)
511 {
512 return MEMCACHED_INVALID_ARGUMENTS;
513 }
514
515 if (ptr and ptr->error_messages)
516 {
517 return ptr->error_messages->rc;
518 }
519
520 return MEMCACHED_SUCCESS;
521 }