Update all of the delete key logic (split it off for ASCII)
[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 <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 {
66 return;
67 }
68
69 memcpy(error, memc.error_messages, sizeof(memcached_error_t));
70 error->next= server.error_messages;
71 server.error_messages= error;
72 }
73
74 static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
75 {
76 (void)at;
77 if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
78 {
79 memcached_error_free(memc);
80 }
81
82 // For memory allocation we use our error since it is a bit more specific
83 if (local_errno == ENOMEM and rc == MEMCACHED_ERRNO)
84 {
85 rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
86 }
87
88 if (rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
89 {
90 local_errno= ENOMEM;
91 }
92
93 if (rc == MEMCACHED_ERRNO and not local_errno)
94 {
95 local_errno= errno;
96 rc= MEMCACHED_ERRNO;
97 }
98
99 if (rc == MEMCACHED_ERRNO and local_errno == ENOTCONN)
100 {
101 rc= MEMCACHED_CONNECTION_FAILURE;
102 }
103
104 if (local_errno == EINVAL)
105 {
106 rc= MEMCACHED_INVALID_ARGUMENTS;
107 }
108
109 if (local_errno == ECONNREFUSED)
110 {
111 rc= MEMCACHED_CONNECTION_FAILURE;
112 }
113
114 memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
115 if (not error) // Bad business if this happens
116 return;
117
118 error->root= &memc;
119 error->query_id= memc.query_id;
120 error->rc= rc;
121 error->local_errno= local_errno;
122
123 const char *errmsg_ptr;
124 char errmsg[MAX_ERROR_LENGTH];
125 errmsg[0]= 0;
126 errmsg_ptr= errmsg;
127
128 if (local_errno)
129 {
130 #ifdef STRERROR_R_CHAR_P
131 errmsg_ptr= strerror_r(local_errno, errmsg, sizeof(errmsg));
132 #else
133 strerror_r(local_errno, errmsg, sizeof(errmsg));
134 errmsg_ptr= errmsg;
135 #endif
136 }
137
138
139 if (str and str->size and local_errno)
140 {
141 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s), %.*s -> %s",
142 memcached_strerror(&memc, rc),
143 errmsg_ptr,
144 memcached_string_printf(*str), at);
145 }
146 else if (local_errno)
147 {
148 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s) -> %s",
149 memcached_strerror(&memc, rc),
150 errmsg_ptr,
151 at);
152 }
153 else if (rc == MEMCACHED_PARSE_ERROR and str and str->size)
154 {
155 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%.*s -> %s",
156 int(str->size), str->c_str, at);
157 }
158 else if (str and str->size)
159 {
160 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s, %.*s -> %s",
161 memcached_strerror(&memc, rc),
162 int(str->size), str->c_str, at);
163 }
164 else
165 {
166 error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s -> %s",
167 memcached_strerror(&memc, rc), at);
168 }
169
170 error->next= memc.error_messages;
171 memc.error_messages= error;
172 }
173
174 memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, const char *str, size_t length)
175 {
176 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
177 memcached_string_t tmp= { str, length };
178 return memcached_set_error(memc, rc, at, tmp);
179 }
180
181 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at, const char *str, size_t length)
182 {
183 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
184 assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
185 memcached_string_t tmp= { str, length };
186 return memcached_set_error(self, rc, at, tmp);
187 }
188
189 memcached_return_t memcached_set_error(memcached_st& memc, memcached_return_t rc, const char *at, memcached_string_t& str)
190 {
191 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
192 if (memcached_success(rc))
193 return MEMCACHED_SUCCESS;
194
195 _set(memc, &str, rc, at);
196
197 return rc;
198 }
199
200 memcached_return_t memcached_set_parser_error(memcached_st& memc,
201 const char *at,
202 const char *format, ...)
203 {
204 va_list args;
205
206 char buffer[BUFSIZ];
207 va_start(args, format);
208 int length= vsnprintf(buffer, sizeof(buffer), format, args);
209 va_end(args);
210
211 return memcached_set_error(memc, MEMCACHED_PARSE_ERROR, at, buffer, length);
212 }
213
214 memcached_return_t memcached_set_error(memcached_server_st& self, memcached_return_t rc, const char *at, memcached_string_t& str)
215 {
216 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
217 assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
218 if (memcached_success(rc))
219 return MEMCACHED_SUCCESS;
220
221 char hostname_port_message[MAX_ERROR_LENGTH];
222 int size;
223 if (str.size)
224 {
225 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d",
226 memcached_string_printf(str),
227 self.hostname, int(self.port));
228 }
229 else
230 {
231 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
232 self.hostname, int(self.port));
233 }
234
235 memcached_string_t error_host= { hostname_port_message, 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_server_st& self, memcached_return_t rc, const char *at)
247 {
248 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
249 assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_server_st");
250 if (memcached_success(rc))
251 return MEMCACHED_SUCCESS;
252
253 char hostname_port[NI_MAXHOST +NI_MAXSERV + sizeof("host : ")];
254 int size= snprintf(hostname_port, sizeof(hostname_port), "host: %s:%d", self.hostname, int(self.port));
255
256 memcached_string_t error_host= { hostname_port, size};
257
258 if (not self.root)
259 return rc;
260
261 _set(*self.root, &error_host, rc, at);
262 _set(self, *self.root);
263
264 return rc;
265 }
266
267 memcached_return_t memcached_set_error(memcached_st& self, memcached_return_t rc, const char *at)
268 {
269 assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
270 if (memcached_success(rc))
271 return MEMCACHED_SUCCESS;
272
273 _set(self, NULL, rc, at);
274
275 return rc;
276 }
277
278 memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at, const char *str, size_t length)
279 {
280 memcached_string_t tmp= { str, length };
281 return memcached_set_errno(self, local_errno, at, tmp);
282 }
283
284 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at, const char *str, size_t length)
285 {
286 memcached_string_t tmp= { str, length };
287 return memcached_set_errno(self, local_errno, at, tmp);
288 }
289
290 memcached_return_t memcached_set_errno(memcached_st& self, int local_errno, const char *at)
291 {
292 if (not local_errno)
293 return MEMCACHED_SUCCESS;
294
295 memcached_return_t rc= MEMCACHED_ERRNO;
296 _set(self, NULL, rc, at, local_errno);
297
298 return rc;
299 }
300
301 memcached_return_t memcached_set_errno(memcached_st& memc, int local_errno, const char *at, memcached_string_t& str)
302 {
303 if (not local_errno)
304 return MEMCACHED_SUCCESS;
305
306 memcached_return_t rc= MEMCACHED_ERRNO;
307 _set(memc, &str, rc, at, local_errno);
308
309 return rc;
310 }
311
312 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at, memcached_string_t& str)
313 {
314 if (not local_errno)
315 return MEMCACHED_SUCCESS;
316
317 char hostname_port_message[MAX_ERROR_LENGTH];
318 int size;
319 if (str.size)
320 {
321 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "%.*s, host: %s:%d",
322 memcached_string_printf(str),
323 self.hostname, int(self.port));
324 }
325 else
326 {
327 size= snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
328 self.hostname, int(self.port));
329 }
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 memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errno, const char *at)
344 {
345 if (not local_errno)
346 return MEMCACHED_SUCCESS;
347
348 char hostname_port_message[MAX_ERROR_LENGTH];
349 int size = snprintf(hostname_port_message, sizeof(hostname_port_message), "host: %s:%d",
350 self.hostname, int(self.port));
351
352 memcached_string_t error_host= { hostname_port_message, size };
353
354 memcached_return_t rc= MEMCACHED_ERRNO;
355 if (not self.root)
356 return rc;
357
358 _set(*self.root, &error_host, rc, at, local_errno);
359 _set(self, (*self.root));
360
361 return rc;
362 }
363
364 static void _error_print(const memcached_error_t *error)
365 {
366 if (error == NULL)
367 {
368 return;
369 }
370
371 if (error->size == 0)
372 {
373 fprintf(stderr, "%s\n", memcached_strerror(NULL, error->rc) );
374 }
375 else
376 {
377 fprintf(stderr, "%s %s\n", memcached_strerror(NULL, error->rc), error->message);
378 }
379
380 _error_print(error->next);
381 }
382
383 void memcached_error_print(const memcached_st *self)
384 {
385 if (not self)
386 return;
387
388 _error_print(self->error_messages);
389 }
390
391 static void _error_free(memcached_error_t *error)
392 {
393 if (not error)
394 return;
395
396 _error_free(error->next);
397
398 if (error && error->root)
399 {
400 libmemcached_free(error->root, error);
401 }
402 else if (error)
403 {
404 free(error);
405 }
406 }
407
408 void memcached_error_free(memcached_st& self)
409 {
410 _error_free(self.error_messages);
411 self.error_messages= NULL;
412 }
413
414 void memcached_error_free(memcached_server_st& self)
415 {
416 _error_free(self.error_messages);
417 self.error_messages= NULL;
418 }
419
420 const char *memcached_last_error_message(memcached_st *memc)
421 {
422 if (memc == NULL)
423 {
424 return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
425 }
426
427 if (not memc->error_messages)
428 return memcached_strerror(memc, MEMCACHED_SUCCESS);
429
430 if (not memc->error_messages->size)
431 return memcached_strerror(memc, memc->error_messages->rc);
432
433 return memc->error_messages->message;
434 }
435
436 bool memcached_has_current_error(memcached_st &memc)
437 {
438 if (memc.error_messages
439 and memc.error_messages->query_id == memc.query_id
440 and memcached_failed(memc.error_messages->rc))
441 {
442 return true;
443 }
444
445 return false;
446 }
447
448 bool memcached_has_current_error(memcached_server_st& server)
449 {
450 return memcached_has_current_error(*(server.root));
451 }
452
453 memcached_return_t memcached_last_error(memcached_st *memc)
454 {
455 if (memc == NULL)
456 {
457 return MEMCACHED_INVALID_ARGUMENTS;
458 }
459
460 if (not memc->error_messages)
461 return MEMCACHED_SUCCESS;
462
463 return memc->error_messages->rc;
464 }
465
466 int memcached_last_error_errno(memcached_st *memc)
467 {
468 if (memc == NULL)
469 {
470 return 0;
471 }
472
473 if (not memc->error_messages)
474 {
475 return 0;
476 }
477
478 return memc->error_messages->local_errno;
479 }
480
481 const char *memcached_server_error(memcached_server_instance_st server)
482 {
483 if (server == NULL)
484 {
485 return NULL;
486 }
487
488 if (not server->error_messages)
489 return memcached_strerror(server->root, MEMCACHED_SUCCESS);
490
491 if (not server->error_messages->size)
492 return memcached_strerror(server->root, server->error_messages->rc);
493
494 return server->error_messages->message;
495 }
496
497
498 memcached_error_t *memcached_error_copy(const memcached_server_st& server)
499 {
500 if (server.error_messages == NULL)
501 {
502 return NULL;
503 }
504
505 memcached_error_t *error= (memcached_error_t *)libmemcached_malloc(server.root, sizeof(memcached_error_t));
506 memcpy(error, server.error_messages, sizeof(memcached_error_t));
507 error->next= NULL;
508
509 return error;
510 }
511
512 memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr)
513 {
514 if (ptr == NULL)
515 {
516 return MEMCACHED_INVALID_ARGUMENTS;
517 }
518
519 if (ptr and ptr->error_messages)
520 {
521 return ptr->error_messages->rc;
522 }
523
524 return MEMCACHED_SUCCESS;
525 }