Merge in all of build.
[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
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, const memcached_return_t rc, const int local_errno)
53 {
54 WATCHPOINT_ASSERT(memc);
55 if (! 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 memcached_error_t *error;
64 error= (struct memcached_error_t *)libmemcached_malloc(memc, sizeof(struct memcached_error_t));
65
66 if (! error)
67 return;
68
69 error->root= memc;
70 error->query_id= memc->query_id;
71 error->rc= rc;
72 error->local_errno= local_errno;
73
74 if (str)
75 {
76 size_t length= str->size > (size_t)MAX_ERROR_LENGTH ? MAX_ERROR_LENGTH : str->size;
77 error->size= length;
78 memcpy(error->message, str->c_str, error->size);
79 error->message[error->size]= 0;
80 }
81 else
82 {
83 error->size= 0;
84 }
85
86 error->next= memc->error_messages;
87 memc->error_messages= error;
88 }
89
90 memcached_return_t memcached_set_error_string(memcached_st *memc, memcached_return_t rc, const char *str, size_t length)
91 {
92 memcached_string_t tmp;
93 tmp.c_str= str;
94 tmp.size= length;
95 return memcached_set_error(memc, rc, &tmp);
96 }
97
98 memcached_return_t memcached_set_error(memcached_st *memc, memcached_return_t rc, memcached_string_t *str)
99 {
100 if (rc == MEMCACHED_SUCCESS)
101 return MEMCACHED_SUCCESS;
102
103 _set(memc, str, rc, 0);
104
105 return rc;
106 }
107
108 memcached_return_t memcached_set_errno(memcached_st *memc, int local_errno, memcached_string_t *str)
109 {
110 _set(memc, str, MEMCACHED_ERRNO, local_errno);
111
112 return MEMCACHED_ERRNO;
113 }
114
115 static void _error_print(const memcached_error_t *error)
116 {
117 if (! error)
118 return;
119
120 if (! error->size)
121 {
122 fprintf(stderr, "%s\n", memcached_strerror(NULL, error->rc) );
123 }
124 else
125 {
126 fprintf(stderr, "%s %s\n", memcached_strerror(NULL, error->rc), error->message);
127 }
128
129 _error_print(error->next);
130 }
131
132 void memcached_error_print(const memcached_st *self)
133 {
134 if (! self)
135 return;
136
137 _error_print(self->error_messages);
138 }
139
140 static void _error_free(memcached_error_t *error)
141 {
142 if (! error)
143 return;
144
145 _error_free(error->next);
146
147 if (error && error->root)
148 {
149 libmemcached_free(error->root, error);
150 }
151 else if (error)
152 {
153 free(error);
154 }
155 }
156
157 void memcached_error_free(memcached_st *self)
158 {
159 if (! self)
160 return;
161
162 _error_free(self->error_messages);
163 }
164
165 const char *memcached_last_error_message(memcached_st *memc)
166 {
167 if (! memc)
168 return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
169
170 if (! memc->error_messages)
171 return memcached_strerror(memc, MEMCACHED_SUCCESS);
172
173 if (! memc->error_messages->size)
174 {
175 return memcached_strerror(memc, memc->error_messages->rc);
176 }
177
178 return memc->error_messages->message;
179 }
180
181 memcached_return_t memcached_last_error(memcached_st *memc)
182 {
183 if (! memc)
184 return MEMCACHED_INVALID_ARGUMENTS;
185
186 if (! memc->error_messages)
187 return MEMCACHED_SUCCESS;
188
189 return memc->error_messages->rc;
190 }
191
192 int memcached_last_error_errno(memcached_st *memc)
193 {
194 if (! memc)
195 return 0;
196
197 if (! memc->error_messages)
198 return 0;
199
200 return memc->error_messages->local_errno;
201 }