1 /* Copyright (c) 2009, 2010, 2011 Nicira Networks
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
18 #include "ovsdb-error.h"
22 #include "backtrace.h"
23 #include "dynamic-string.h"
28 VLOG_DEFINE_THIS_MODULE(ovsdb_error);
31 const char *tag; /* String for "error" member. */
32 char *details; /* String for "details" member. */
33 char *syntax; /* String for "syntax" member. */
34 int errno_; /* Unix errno value, 0 if none. */
37 static struct ovsdb_error *
38 ovsdb_error_valist(const char *tag, const char *details, va_list args)
40 struct ovsdb_error *error = xmalloc(sizeof *error);
41 error->tag = tag ? tag : "ovsdb error";
42 error->details = details ? xvasprintf(details, args) : NULL;
49 ovsdb_error(const char *tag, const char *details, ...)
51 struct ovsdb_error *error;
54 va_start(args, details);
55 error = ovsdb_error_valist(tag, details, args);
62 ovsdb_io_error(int errno_, const char *details, ...)
64 struct ovsdb_error *error;
67 va_start(args, details);
68 error = ovsdb_error_valist("I/O error", details, args);
71 error->errno_ = errno_;
77 ovsdb_syntax_error(const struct json *json, const char *tag,
78 const char *details, ...)
80 struct ovsdb_error *error;
83 va_start(args, details);
84 error = ovsdb_error_valist(tag ? tag : "syntax error", details, args);
88 /* XXX this is much too much information in some cases */
89 error->syntax = json_to_string(json, JSSF_SORT);
96 ovsdb_wrap_error(struct ovsdb_error *error, const char *details, ...)
101 va_start(args, details);
102 msg = xvasprintf(details, args);
105 if (error->details) {
106 char *new = xasprintf("%s: %s", msg, error->details);
107 free(error->details);
108 error->details = new;
111 error->details = msg;
117 /* Returns an ovsdb_error that represents an internal error for file name
118 * 'file' and line number 'line', with 'details' (formatted as with printf())
119 * as the associated message. The caller is responsible for freeing the
122 * If 'inner_error' is nonnull then the returned error is wrapped around
123 * 'inner_error'. Takes ownership of 'inner_error'. */
125 ovsdb_internal_error(struct ovsdb_error *inner_error,
126 const char *file, int line, const char *details, ...)
128 struct ds ds = DS_EMPTY_INITIALIZER;
129 struct backtrace backtrace;
130 struct ovsdb_error *error;
133 ds_put_format(&ds, "%s:%d:", file, line);
136 ds_put_char(&ds, ' ');
137 va_start(args, details);
138 ds_put_format_valist(&ds, details, args);
142 backtrace_capture(&backtrace);
143 if (backtrace.n_frames) {
146 ds_put_cstr(&ds, " (backtrace:");
147 for (i = 0; i < backtrace.n_frames; i++) {
148 ds_put_format(&ds, " 0x%08"PRIxPTR, backtrace.frames[i]);
150 ds_put_char(&ds, ')');
153 ds_put_format(&ds, " (%s %s%s)", program_name, VERSION, BUILDNR);
156 char *s = ovsdb_error_to_string(inner_error);
157 ds_put_format(&ds, " (generated from: %s)", s);
160 ovsdb_error_destroy(inner_error);
163 error = ovsdb_error("internal error", "%s", ds_cstr(&ds));
171 ovsdb_error_destroy(struct ovsdb_error *error)
174 free(error->details);
181 ovsdb_error_clone(const struct ovsdb_error *old)
184 struct ovsdb_error *new = xmalloc(sizeof *new);
186 new->details = old->details ? xstrdup(old->details) : NULL;
187 new->syntax = old->syntax ? xstrdup(old->syntax) : NULL;
188 new->errno_ = old->errno_;
196 ovsdb_errno_string(int error)
198 return error == EOF ? "unexpected end of file" : strerror(error);
202 ovsdb_error_to_json(const struct ovsdb_error *error)
204 struct json *json = json_object_create();
205 json_object_put_string(json, "error", error->tag);
206 if (error->details) {
207 json_object_put_string(json, "details", error->details);
210 json_object_put_string(json, "syntax", error->syntax);
213 json_object_put_string(json, "io-error",
214 ovsdb_errno_string(error->errno_));
220 ovsdb_error_to_string(const struct ovsdb_error *error)
222 struct ds ds = DS_EMPTY_INITIALIZER;
224 ds_put_format(&ds, "syntax \"%s\": ", error->syntax);
226 ds_put_cstr(&ds, error->tag);
227 if (error->details) {
228 ds_put_format(&ds, ": %s", error->details);
231 ds_put_format(&ds, " (%s)", ovsdb_errno_string(error->errno_));
233 return ds_steal_cstr(&ds);
237 ovsdb_error_get_tag(const struct ovsdb_error *error)
242 /* If 'error' is nonnull, logs it as an error and frees it. To be used in
243 * situations where an error should never occur, but an 'ovsdb_error *' gets
244 * passed back anyhow. */
246 ovsdb_error_assert(struct ovsdb_error *error)
249 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
250 char *s = ovsdb_error_to_string(error);
251 VLOG_ERR_RL(&rl, "unexpected ovsdb error: %s", s);
253 ovsdb_error_destroy(error);