Fixed up a few more places where we set the error in the memcached root.
[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_message(memc, rc, &tmp);
96 }
97
98 memcached_return_t memcached_set_error_message(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_error(memcached_st *memc, memcached_return_t rc)
109 {
110 if (rc == MEMCACHED_SUCCESS)
111 return MEMCACHED_SUCCESS;
112
113 _set(memc, NULL, rc, 0);
114
115 return rc;
116 }
117
118 memcached_return_t memcached_set_errno(memcached_st *memc, int local_errno, memcached_string_t *str)
119 {
120 _set(memc, str, MEMCACHED_ERRNO, local_errno);
121
122 return MEMCACHED_ERRNO;
123 }
124
125 static void _error_print(const memcached_error_t *error)
126 {
127 if (! error)
128 return;
129
130 if (! error->size)
131 {
132 fprintf(stderr, "%s\n", memcached_strerror(NULL, error->rc) );
133 }
134 else
135 {
136 fprintf(stderr, "%s %s\n", memcached_strerror(NULL, error->rc), error->message);
137 }
138
139 _error_print(error->next);
140 }
141
142 void memcached_error_print(const memcached_st *self)
143 {
144 if (! self)
145 return;
146
147 _error_print(self->error_messages);
148 }
149
150 static void _error_free(memcached_error_t *error)
151 {
152 if (not error)
153 return;
154
155 _error_free(error->next);
156
157 if (error && error->root)
158 {
159 libmemcached_free(error->root, error);
160 }
161 else if (error)
162 {
163 free(error);
164 }
165 }
166
167 void memcached_error_free(memcached_st *self)
168 {
169 if (not self)
170 return;
171
172 _error_free(self->error_messages);
173 self->error_messages= NULL;
174 }
175
176 const char *memcached_last_error_message(memcached_st *memc)
177 {
178 if (! memc)
179 return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
180
181 if (! memc->error_messages)
182 return memcached_strerror(memc, MEMCACHED_SUCCESS);
183
184 if (! memc->error_messages->size)
185 {
186 return memcached_strerror(memc, memc->error_messages->rc);
187 }
188
189 return memc->error_messages->message;
190 }
191
192 memcached_return_t memcached_last_error(memcached_st *memc)
193 {
194 if (! memc)
195 return MEMCACHED_INVALID_ARGUMENTS;
196
197 if (! memc->error_messages)
198 return MEMCACHED_SUCCESS;
199
200 return memc->error_messages->rc;
201 }
202
203 int memcached_last_error_errno(memcached_st *memc)
204 {
205 if (! memc)
206 return 0;
207
208 if (! memc->error_messages)
209 return 0;
210
211 return memc->error_messages->local_errno;
212 }