diff options
| author | Ben Pfaff <blp@nicira.com> | 2009-11-04 15:11:44 -0800 |
|---|---|---|
| committer | Ben Pfaff <blp@nicira.com> | 2009-11-04 17:12:10 -0800 |
| commit | f85f8ebbfac946c19b3c6eb0f4170f579d0a4d25 (patch) | |
| tree | 2111aee77751f2143773907f81c6adb9101afb6c /lib/ovsdb-error.c | |
| parent | f212909325be9bc7e296e1a32e2fc89694a0049f (diff) | |
| download | openvswitch-f85f8ebbfac946c19b3c6eb0f4170f579d0a4d25.tar.gz | |
Initial implementation of OVSDB.
Diffstat (limited to 'lib/ovsdb-error.c')
| -rw-r--r-- | lib/ovsdb-error.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/lib/ovsdb-error.c b/lib/ovsdb-error.c new file mode 100644 index 000000000..c0eddf280 --- /dev/null +++ b/lib/ovsdb-error.c @@ -0,0 +1,221 @@ +/* Copyright (c) 2009 Nicira Networks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> + +#include "ovsdb-error.h" + +#include <inttypes.h> + +#include "backtrace.h" +#include "dynamic-string.h" +#include "json.h" +#include "util.h" + +struct ovsdb_error { + const char *tag; /* String for "error" member. */ + char *details; /* String for "details" member. */ + char *syntax; /* String for "syntax" member. */ + int errno_; /* Unix errno value, 0 if none. */ +}; + +static struct ovsdb_error * +ovsdb_error_valist(const char *tag, const char *details, va_list args) +{ + struct ovsdb_error *error = xmalloc(sizeof *error); + error->tag = tag ? tag : "ovsdb error"; + error->details = details ? xvasprintf(details, args) : NULL; + error->syntax = NULL; + error->errno_ = 0; + return error; +} + +struct ovsdb_error * +ovsdb_error(const char *tag, const char *details, ...) +{ + struct ovsdb_error *error; + va_list args; + + va_start(args, details); + error = ovsdb_error_valist(tag, details, args); + va_end(args); + + return error; +} + +struct ovsdb_error * +ovsdb_io_error(int errno_, const char *details, ...) +{ + struct ovsdb_error *error; + va_list args; + + va_start(args, details); + error = ovsdb_error_valist("I/O error", details, args); + va_end(args); + + error->errno_ = errno_; + + return error; +} + +struct ovsdb_error * +ovsdb_syntax_error(const struct json *json, const char *tag, + const char *details, ...) +{ + struct ovsdb_error *error; + va_list args; + + va_start(args, details); + error = ovsdb_error_valist(tag ? tag : "syntax error", details, args); + va_end(args); + + if (json) { + /* XXX this is much too much information in some cases */ + error->syntax = json_to_string(json, 0); + } + + return error; +} + +struct ovsdb_error * +ovsdb_wrap_error(struct ovsdb_error *error, const char *details, ...) +{ + va_list args; + char *msg; + + va_start(args, details); + msg = xvasprintf(details, args); + va_end(args); + + if (error->details) { + char *new = xasprintf("%s: %s", msg, error->details); + free(error->details); + error->details = new; + free(msg); + } else { + error->details = msg; + } + + return error; +} + +struct ovsdb_error * +ovsdb_internal_error(const char *file, int line, const char *details, ...) +{ + struct ds ds = DS_EMPTY_INITIALIZER; + struct backtrace backtrace; + struct ovsdb_error *error; + va_list args; + + ds_put_format(&ds, "%s:%d:", file, line); + + if (details) { + ds_put_char(&ds, ' '); + va_start(args, details); + ds_put_format_valist(&ds, details, args); + va_end(args); + } + + backtrace_capture(&backtrace); + if (backtrace.n_frames) { + int i; + + ds_put_cstr(&ds, " (backtrace:"); + for (i = 0; i < backtrace.n_frames; i++) { + ds_put_format(&ds, " 0x%08"PRIxPTR, backtrace.frames[i]); + } + ds_put_char(&ds, ')'); + } + + ds_put_format(&ds, " (%s %s%s)", program_name, VERSION, BUILDNR); + + error = ovsdb_error("internal error", "%s", ds_cstr(&ds)); + + ds_destroy(&ds); + + return error; +} + +void +ovsdb_error_destroy(struct ovsdb_error *error) +{ + if (error) { + free(error->details); + free(error->syntax); + free(error); + } +} + +struct ovsdb_error * +ovsdb_error_clone(const struct ovsdb_error *old) +{ + if (old) { + struct ovsdb_error *new = xmalloc(sizeof *new); + new->tag = old->tag; + new->details = old->details ? xstrdup(old->details) : NULL; + new->syntax = old->syntax ? xstrdup(old->syntax) : NULL; + new->errno_ = old->errno_; + return new; + } else { + return NULL; + } +} + +static const char * +ovsdb_errno_string(int error) +{ + return error == EOF ? "unexpected end of file" : strerror(error); +} + +struct json * +ovsdb_error_to_json(const struct ovsdb_error *error) +{ + struct json *json = json_object_create(); + json_object_put_string(json, "error", error->tag); + if (error->details) { + json_object_put_string(json, "details", error->details); + } + if (error->syntax) { + json_object_put_string(json, "syntax", error->syntax); + } + if (error->errno_) { + json_object_put_string(json, "io-error", + ovsdb_errno_string(error->errno_)); + } + return json; +} + +char * +ovsdb_error_to_string(const struct ovsdb_error *error) +{ + struct ds ds = DS_EMPTY_INITIALIZER; + if (error->syntax) { + ds_put_format(&ds, "syntax \"%s\": ", error->syntax); + } + ds_put_cstr(&ds, error->tag); + if (error->details) { + ds_put_format(&ds, ": %s", error->details); + } + if (error->errno_) { + ds_put_format(&ds, " (%s)", ovsdb_errno_string(error->errno_)); + } + return ds_steal_cstr(&ds); +} + +const char * +ovsdb_error_get_tag(const struct ovsdb_error *error) +{ + return error->tag; +} |
