]> git.proxmox.com Git - mirror_ovs.git/blame - lib/ovsdb-error.c
Always treat datapath ports as 32 bits.
[mirror_ovs.git] / lib / ovsdb-error.c
CommitLineData
e0edde6f 1/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
f85f8ebb
BP
2 *
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:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
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.
14 */
15
16#include <config.h>
17
18#include "ovsdb-error.h"
19
20#include <inttypes.h>
21
22#include "backtrace.h"
23#include "dynamic-string.h"
24#include "json.h"
25#include "util.h"
80af01ed
BP
26#include "vlog.h"
27
d98e6007 28VLOG_DEFINE_THIS_MODULE(ovsdb_error);
f85f8ebb
BP
29
30struct 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. */
35};
36
37static struct ovsdb_error *
38ovsdb_error_valist(const char *tag, const char *details, va_list args)
39{
40 struct ovsdb_error *error = xmalloc(sizeof *error);
41 error->tag = tag ? tag : "ovsdb error";
42 error->details = details ? xvasprintf(details, args) : NULL;
43 error->syntax = NULL;
44 error->errno_ = 0;
45 return error;
46}
47
48struct ovsdb_error *
49ovsdb_error(const char *tag, const char *details, ...)
50{
51 struct ovsdb_error *error;
52 va_list args;
53
54 va_start(args, details);
55 error = ovsdb_error_valist(tag, details, args);
56 va_end(args);
57
58 return error;
59}
60
61struct ovsdb_error *
62ovsdb_io_error(int errno_, const char *details, ...)
63{
64 struct ovsdb_error *error;
65 va_list args;
66
67 va_start(args, details);
68 error = ovsdb_error_valist("I/O error", details, args);
69 va_end(args);
70
71 error->errno_ = errno_;
72
73 return error;
74}
75
76struct ovsdb_error *
77ovsdb_syntax_error(const struct json *json, const char *tag,
78 const char *details, ...)
79{
80 struct ovsdb_error *error;
81 va_list args;
82
83 va_start(args, details);
84 error = ovsdb_error_valist(tag ? tag : "syntax error", details, args);
85 va_end(args);
86
87 if (json) {
88 /* XXX this is much too much information in some cases */
62c87d4a 89 error->syntax = json_to_string(json, JSSF_SORT);
f85f8ebb
BP
90 }
91
92 return error;
93}
94
95struct ovsdb_error *
96ovsdb_wrap_error(struct ovsdb_error *error, const char *details, ...)
97{
98 va_list args;
99 char *msg;
100
101 va_start(args, details);
102 msg = xvasprintf(details, args);
103 va_end(args);
104
105 if (error->details) {
106 char *new = xasprintf("%s: %s", msg, error->details);
107 free(error->details);
108 error->details = new;
109 free(msg);
110 } else {
111 error->details = msg;
112 }
113
114 return error;
115}
116
1dd5b71d
BP
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
120 * returned error.
121 *
122 * If 'inner_error' is nonnull then the returned error is wrapped around
123 * 'inner_error'. Takes ownership of 'inner_error'. */
f85f8ebb 124struct ovsdb_error *
1dd5b71d
BP
125ovsdb_internal_error(struct ovsdb_error *inner_error,
126 const char *file, int line, const char *details, ...)
f85f8ebb
BP
127{
128 struct ds ds = DS_EMPTY_INITIALIZER;
129 struct backtrace backtrace;
130 struct ovsdb_error *error;
131 va_list args;
132
133 ds_put_format(&ds, "%s:%d:", file, line);
134
135 if (details) {
136 ds_put_char(&ds, ' ');
137 va_start(args, details);
138 ds_put_format_valist(&ds, details, args);
139 va_end(args);
140 }
141
142 backtrace_capture(&backtrace);
143 if (backtrace.n_frames) {
144 int i;
145
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]);
149 }
150 ds_put_char(&ds, ')');
151 }
152
8a07709c 153 ds_put_format(&ds, " (%s %s)", program_name, VERSION);
f85f8ebb 154
1dd5b71d
BP
155 if (inner_error) {
156 char *s = ovsdb_error_to_string(inner_error);
157 ds_put_format(&ds, " (generated from: %s)", s);
158 free(s);
159
160 ovsdb_error_destroy(inner_error);
161 }
162
f85f8ebb
BP
163 error = ovsdb_error("internal error", "%s", ds_cstr(&ds));
164
165 ds_destroy(&ds);
166
167 return error;
168}
169
170void
171ovsdb_error_destroy(struct ovsdb_error *error)
172{
173 if (error) {
174 free(error->details);
175 free(error->syntax);
176 free(error);
177 }
178}
179
180struct ovsdb_error *
181ovsdb_error_clone(const struct ovsdb_error *old)
182{
183 if (old) {
184 struct ovsdb_error *new = xmalloc(sizeof *new);
185 new->tag = old->tag;
186 new->details = old->details ? xstrdup(old->details) : NULL;
187 new->syntax = old->syntax ? xstrdup(old->syntax) : NULL;
188 new->errno_ = old->errno_;
189 return new;
190 } else {
191 return NULL;
192 }
193}
194
f85f8ebb
BP
195struct json *
196ovsdb_error_to_json(const struct ovsdb_error *error)
197{
198 struct json *json = json_object_create();
199 json_object_put_string(json, "error", error->tag);
200 if (error->details) {
201 json_object_put_string(json, "details", error->details);
202 }
203 if (error->syntax) {
204 json_object_put_string(json, "syntax", error->syntax);
205 }
206 if (error->errno_) {
207 json_object_put_string(json, "io-error",
fe1e967e 208 ovs_retval_to_string(error->errno_));
f85f8ebb
BP
209 }
210 return json;
211}
212
213char *
214ovsdb_error_to_string(const struct ovsdb_error *error)
215{
216 struct ds ds = DS_EMPTY_INITIALIZER;
217 if (error->syntax) {
218 ds_put_format(&ds, "syntax \"%s\": ", error->syntax);
219 }
220 ds_put_cstr(&ds, error->tag);
221 if (error->details) {
222 ds_put_format(&ds, ": %s", error->details);
223 }
224 if (error->errno_) {
fe1e967e 225 ds_put_format(&ds, " (%s)", ovs_retval_to_string(error->errno_));
f85f8ebb
BP
226 }
227 return ds_steal_cstr(&ds);
228}
229
230const char *
231ovsdb_error_get_tag(const struct ovsdb_error *error)
232{
233 return error->tag;
234}
80af01ed
BP
235
236/* If 'error' is nonnull, logs it as an error and frees it. To be used in
237 * situations where an error should never occur, but an 'ovsdb_error *' gets
238 * passed back anyhow. */
239void
240ovsdb_error_assert(struct ovsdb_error *error)
241{
242 if (error) {
243 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
244 char *s = ovsdb_error_to_string(error);
245 VLOG_ERR_RL(&rl, "unexpected ovsdb error: %s", s);
246 free(s);
247 ovsdb_error_destroy(error);
248 }
249}