All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
as_error.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2023 Aerospike, Inc.
3  *
4  * Portions may be licensed to Aerospike, Inc. under one or more contributor
5  * license agreements.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8  * use this file except in compliance with the License. You may obtain a copy of
9  * the License at http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17 #pragma once
18 
19 #include <aerospike/as_std.h>
20 #include <aerospike/as_status.h>
21 #include <aerospike/as_string.h>
22 
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 /******************************************************************************
32  * MACROS
33  *****************************************************************************/
34 
35 /**
36  * The size of as_error.message
37  *
38  * @ingroup as_error_object
39  */
40 #define AS_ERROR_MESSAGE_MAX_SIZE 1024
41 
42 /**
43  * The maximum string length of as_error.message
44  *
45  * @ingroup as_error_object
46  */
47 #define AS_ERROR_MESSAGE_MAX_LEN (AS_ERROR_MESSAGE_MAX_SIZE - 1)
48 
49 /******************************************************************************
50  * TYPES
51  *****************************************************************************/
52 
53 /**
54  * All operations that interact with the Aerospike cluster accept an as_error
55  * argument and return an as_status value. The as_error argument is populated
56  * with information about the error that occurred. The as_status return value
57  * is the as_error.code value.
58  *
59  * When an operation succeeds, the as_error.code value is usually set to
60  * `AEROSPIKE_OK`. There are some operations which may have other success
61  * status codes, so please review each operation for information on status
62  * codes.
63  *
64  * When as_error.code is not a success value (`AEROSPIKE_OK`), then you can
65  * expect the other fields of as_error.code to be populated.
66  *
67  * Example usage:
68  * ~~~~~~~~~~{.c}
69  * as_error err;
70  *
71  * if ( aerospike_key_get(&as, &err, NULL, &key, &rec) != AEROSPIKE_OK ) {
72  * fprintf(stderr, "(%d) %s at %s[%s:%d]\n", error.code, err.message, err.func, err.file. err.line);
73  * }
74  * ~~~~~~~~~~
75  *
76  * You can reuse an as_error with multiple operations. Each operation
77  * internally resets the error. So, if an error occurred in one operation,
78  * and you did not check it, then the error will be lost with subsequent
79  * operations.
80  *
81  * Example usage:
82  *
83  * ~~~~~~~~~~{.c}
84  * as_error err;
85  *
86  * if ( aerospike_key_put(&as, &err, NULL, &key, rec) != AEROSPIKE_OK ) {
87  * fprintf(stderr, "(%d) %s at %s[%s:%d]\n", error.code, err.message, err.func, err.file. err.line);
88  * }
89  *
90  * if ( aerospike_key_get(&as, &err, NULL, &key, &rec) != AEROSPIKE_OK ) {
91  * fprintf(stderr, "(%d) %s at %s[%s:%d]\n", error.code, err.message, err.func, err.file. err.line);
92  * }
93  * ~~~~~~~~~~
94  *
95  * @ingroup client_objects
96  */
97 typedef struct as_error_s {
98 
99  /**
100  * Numeric error code
101  */
103 
104  /**
105  * NULL-terminated error message
106  */
108 
109  /**
110  * Name of the function where the error occurred.
111  */
112  const char * func;
113 
114  /**
115  * Name of the file where the error occurred.
116  */
117  const char * file;
118 
119  /**
120  * Line in the file where the error occurred.
121  */
122  uint32_t line;
123 
124  /**
125  * Is it possible that the write transaction completed even though this error was generated.
126  * This may be the case when a client error occurs (like timeout) after the command was sent
127  * to the server.
128  */
129  bool in_doubt;
130 
131 } as_error;
132 
133 /******************************************************************************
134  * MACROS
135  *****************************************************************************/
136 
137 /**
138  * Set all as_error fields and default in_doubt to false. Variable arguments are accepted.
139  *
140  * @ingroup as_error_object
141  */
142 #define as_error_update(__err, __code, __fmt, ...) \
143  as_error_setallv( __err, __code, __func__, __FILE__, __LINE__, __fmt, ##__VA_ARGS__ );
144 
145 /**
146  * Set all as_error fields and default in_doubt to false. Variable arguments are not accepted.
147  *
148  * @ingroup as_error_object
149  */
150 #define as_error_set_message(__err, __code, __msg) \
151  as_error_setall( __err, __code, __msg, __func__, __FILE__, __LINE__ );
152 
153 /******************************************************************************
154  * FUNCTIONS
155  *****************************************************************************/
156 
157 /**
158  * Initialize the error to default (empty) values, returning the error.
159  *
160  * @param err The error to initialize.
161  *
162  * @returns The initialized err.
163  *
164  * @relates as_error
165  * @ingroup as_error_object
166  */
167 static inline as_error*
169 {
170  err->code = AEROSPIKE_OK;
171  err->message[0] = '\0';
172  err->func = NULL;
173  err->file = NULL;
174  err->line = 0;
175  err->in_doubt = false;
176  return err;
177 }
178 
179 /**
180  * Resets the error to default (empty) values, returning the status code.
181  *
182  * @param err The error to reset.
183  *
184  * @returns AEROSPIKE_OK.
185  *
186  * @relates as_error
187  * @ingroup as_error_object
188  */
189 static inline as_status
191 {
192  err->code = AEROSPIKE_OK;
193  err->message[0] = '\0';
194  err->func = NULL;
195  err->file = NULL;
196  err->line = 0;
197  err->in_doubt = false;
198  return err->code;
199 }
200 
201 /**
202  * Sets the error.
203  *
204  * @return The status code set for the error.
205  *
206  * @relates as_error
207  */
208 static inline as_status
209 as_error_setall(as_error* err, as_status code, const char * message, const char * func, const char * file, uint32_t line)
210 {
211  err->code = code;
213  err->func = func;
214  err->file = file;
215  err->line = line;
216  err->in_doubt = false;
217  return err->code;
218 }
219 
220 /**
221  * Sets the error.
222  *
223  * @return The status code set for the error.
224  *
225  * @relates as_error
226  */
227 static inline as_status
228 as_error_setallv(as_error* err, as_status code, const char * func, const char * file, uint32_t line, const char * fmt, ...)
229 {
230  if ( fmt != NULL ) {
231  va_list ap;
232  va_start(ap, fmt);
233  vsnprintf(err->message, AS_ERROR_MESSAGE_MAX_LEN, fmt, ap);
234  err->message[AS_ERROR_MESSAGE_MAX_LEN] = '\0';
235  va_end(ap);
236  }
237  err->code = code;
238  err->func = func;
239  err->file = file;
240  err->line = line;
241  err->in_doubt = false;
242  return err->code;
243 }
244 
245 /**
246  * Set whether it is possible that the write transaction may have completed
247  * even though this exception was generated. This may be the case when a
248  * client error occurs (like timeout) after the command was sent to the server.
249  *
250  * @relates as_error
251  */
252 static inline void
253 as_error_set_in_doubt(as_error* err, bool is_read, uint32_t command_sent_counter)
254 {
255  err->in_doubt = (!is_read && (command_sent_counter > 1 || (command_sent_counter == 1 &&
256  (err->code == AEROSPIKE_ERR_TIMEOUT || err->code <= 0))));
257 }
258 
259 /**
260  * Copy error from source to target.
261  *
262  * @relates as_error
263  */
264 static inline void
265 as_error_copy(as_error * trg, const as_error * src)
266 {
267  trg->code = src->code;
268  strcpy(trg->message, src->message);
269  trg->func = src->func;
270  trg->file = src->file;
271  trg->line = src->line;
272  trg->in_doubt = src->in_doubt;
273 }
274 
275 /**
276  * Append string to error message.
277  *
278  * @relates as_error
279  */
280 static inline void
281 as_error_append(as_error* err, const char* str)
282 {
283  strncat(err->message, str, sizeof(err->message) - strlen(err->message) - 1);
284 }
285 
286 /**
287  * Return string representation of error code. Result should not be freed.
288  *
289  * @relates as_error
290  */
291 AS_EXTERN char*
292 as_error_string(as_status status);
293 
294 #ifdef __cplusplus
295 } // end extern "C"
296 #endif
#define AS_ERROR_MESSAGE_MAX_LEN
Definition: as_error.h:47
as_status
Definition: as_status.h:30
AS_EXTERN char * as_error_string(as_status status)
char message[AS_ERROR_MESSAGE_MAX_SIZE]
Definition: as_error.h:107
static void as_error_copy(as_error *trg, const as_error *src)
Definition: as_error.h:265
const char * file
Definition: as_error.h:117
#define AS_EXTERN
Definition: as_std.h:25
static as_error * as_error_init(as_error *err)
Definition: as_error.h:168
const char * func
Definition: as_error.h:112
static void as_error_append(as_error *err, const char *str)
Definition: as_error.h:281
static void as_error_set_in_doubt(as_error *err, bool is_read, uint32_t command_sent_counter)
Definition: as_error.h:253
#define AS_ERROR_MESSAGE_MAX_SIZE
Definition: as_error.h:40
static as_status as_error_reset(as_error *err)
Definition: as_error.h:190
uint32_t line
Definition: as_error.h:122
as_status code
Definition: as_error.h:102
static as_status as_error_setallv(as_error *err, as_status code, const char *func, const char *file, uint32_t line, const char *fmt,...)
Definition: as_error.h:228
static as_status as_error_setall(as_error *err, as_status code, const char *message, const char *func, const char *file, uint32_t line)
Definition: as_error.h:209
AS_EXTERN bool as_strncpy(char *trg, const char *src, int size)
bool in_doubt
Definition: as_error.h:129