1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Gearmand client and server library.
4 *
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 * Copyright (C) 2008 Brian Aker, Eric Day
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following disclaimer
18 * in the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * * The names of its contributors may not be used to endorse or
22 * promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 */
38
39 #include "gear_config.h"
40 #include <libgearman/common.h>
41
42 #include "libgearman/assert.hpp"
43
44 #include <cerrno>
45 #include <cstdarg>
46 #include <cstdio>
47 #include <cstring>
48
correct_from_errno(gearman_universal_st & universal)49 static void correct_from_errno(gearman_universal_st& universal)
50 {
51 if (universal.error.rc == GEARMAN_ERRNO)
52 {
53 switch (universal.error.last_errno)
54 {
55 case EFAULT:
56 case ENOMEM:
57 universal.error.rc= GEARMAN_MEMORY_ALLOCATION_FAILURE;
58 break;
59
60 case EINVAL:
61 universal.error.rc= GEARMAN_INVALID_ARGUMENT;
62 break;
63
64 case ECONNRESET:
65 case EHOSTDOWN:
66 case EPIPE:
67 universal.error.rc= GEARMAN_LOST_CONNECTION;
68 break;
69
70 case ECONNREFUSED:
71 case ENETUNREACH:
72 case ETIMEDOUT:
73 universal.error.rc= GEARMAN_COULD_NOT_CONNECT;
74 break;
75
76 default:
77 break;
78 }
79 }
80 else
81 {
82 universal.error.last_errno= 0;
83 }
84 }
85
universal_reset_error(gearman_universal_st & universal)86 void universal_reset_error(gearman_universal_st& universal)
87 {
88 universal.error.rc= GEARMAN_SUCCESS;
89 universal.error.last_errno= 0;
90 universal.error.last_error[0]= 0;
91 }
92
93 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
gearman_universal_set_error(gearman_universal_st & universal,gearman_return_t rc,const char * function,const char * position,const char * format,...)94 gearman_return_t gearman_universal_set_error(gearman_universal_st& universal,
95 gearman_return_t rc,
96 const char *function,
97 const char *position,
98 const char *format, ...)
99 {
100 if (rc == GEARMAN_SUCCESS)
101 {
102 return GEARMAN_SUCCESS;
103 }
104
105 va_list args;
106
107 universal.error.rc= rc;
108 correct_from_errno(universal);
109
110 char last_error[GEARMAN_MAX_ERROR_SIZE];
111 va_start(args, format);
112 int length= vsnprintf(last_error, GEARMAN_MAX_ERROR_SIZE, format, args);
113 va_end(args);
114
115 if (length > int(GEARMAN_MAX_ERROR_SIZE) or length < 0)
116 {
117 assert(length > int(GEARMAN_MAX_ERROR_SIZE));
118 assert(length < 0);
119 universal.error.last_error[GEARMAN_MAX_ERROR_SIZE -1]= 0;
120 }
121
122 length= snprintf(universal.error.last_error, GEARMAN_MAX_ERROR_SIZE, "%s(%s) %s -> %s", function, gearman_strerror(universal.error.rc), last_error, position);
123 if (length > int(GEARMAN_MAX_ERROR_SIZE) or length < 0)
124 {
125 assert(length > int(GEARMAN_MAX_ERROR_SIZE));
126 assert(length < 0);
127 universal.error.last_error[GEARMAN_MAX_ERROR_SIZE -1]= 0;
128 }
129
130 if (universal.log_fn)
131 {
132 universal.log_fn(universal.error.last_error,
133 universal.error.rc == GEARMAN_MEMORY_ALLOCATION_FAILURE ? GEARMAN_VERBOSE_FATAL : GEARMAN_VERBOSE_ERROR,
134 static_cast<void *>(universal.log_context));
135 }
136
137 return universal.error.rc;
138 }
139
gearman_universal_set_gerror(gearman_universal_st & universal,gearman_return_t rc,const char * func,const char * position)140 gearman_return_t gearman_universal_set_gerror(gearman_universal_st& universal,
141 gearman_return_t rc,
142 const char *func,
143 const char *position)
144 {
145 if (rc == GEARMAN_SUCCESS or rc == GEARMAN_IO_WAIT)
146 {
147 return rc;
148 }
149
150 universal.error.rc= rc;
151 correct_from_errno(universal);
152
153 int length= snprintf(universal.error.last_error, GEARMAN_MAX_ERROR_SIZE, "%s(%s) -> %s", func, gearman_strerror(rc), position);
154 if (length > int(GEARMAN_MAX_ERROR_SIZE) or length < 0)
155 {
156 assert(length > int(GEARMAN_MAX_ERROR_SIZE));
157 assert(length < 0);
158 universal.error.last_error[GEARMAN_MAX_ERROR_SIZE -1]= 0;
159 return GEARMAN_ARGUMENT_TOO_LARGE;
160 }
161
162 if (universal.log_fn)
163 {
164 universal.log_fn(universal.error.last_error,
165 universal.error.rc == GEARMAN_MEMORY_ALLOCATION_FAILURE ? GEARMAN_VERBOSE_FATAL : GEARMAN_VERBOSE_ERROR,
166 static_cast<void *>(universal.log_context));
167 }
168
169 return rc;
170 }
171
gearman_universal_set_perror(gearman_universal_st & universal,const char * function,const char * position,const char * message)172 gearman_return_t gearman_universal_set_perror(gearman_universal_st &universal,
173 const char *function, const char *position,
174 const char *message)
175 {
176 if (errno == 0)
177 {
178 return GEARMAN_SUCCESS;
179 }
180
181 switch (errno)
182 {
183 case ENOMEM:
184 universal.error.rc= GEARMAN_MEMORY_ALLOCATION_FAILURE;
185 break;
186
187 default:
188 universal.error.rc= GEARMAN_ERRNO;
189 break;
190 }
191 universal.error.last_errno= errno;
192
193 correct_from_errno(universal);
194
195 const char *errmsg_ptr;
196 char errmsg[GEARMAN_MAX_ERROR_SIZE];
197 errmsg[0]= 0;
198
199 #ifdef STRERROR_R_CHAR_P
200 errmsg_ptr= strerror_r(universal.error.last_errno, errmsg, sizeof(errmsg));
201 #else
202 strerror_r(universal.error.last_errno, errmsg, sizeof(errmsg));
203 errmsg_ptr= errmsg;
204 #endif
205
206 int length;
207 if (message)
208 {
209 length= snprintf(universal.error.last_error, GEARMAN_MAX_ERROR_SIZE, "%s(%s) %s -> %s", function, errmsg_ptr, message, position);
210 }
211 else
212 {
213 length= snprintf(universal.error.last_error, GEARMAN_MAX_ERROR_SIZE, "%s(%s) -> %s", function, errmsg_ptr, position);
214 }
215
216 if (length > int(GEARMAN_MAX_ERROR_SIZE) or length < 0)
217 {
218 assert(length > int(GEARMAN_MAX_ERROR_SIZE));
219 assert(length < 0);
220 universal.error.last_error[GEARMAN_MAX_ERROR_SIZE -1]= 0;
221 }
222
223 if (universal.log_fn)
224 {
225 universal.log_fn(universal.error.last_error,
226 universal.error.rc == GEARMAN_MEMORY_ALLOCATION_FAILURE ? GEARMAN_VERBOSE_FATAL : GEARMAN_VERBOSE_ERROR,
227 static_cast<void *>(universal.log_context));
228 }
229
230 return universal.error.rc;
231 }
232