mirror of
				https://github.com/openvswitch/ovs
				synced 2025-10-29 15:28:56 +00:00 
			
		
		
		
	Replaced all instances of Nicira Networks(, Inc) to Nicira, Inc. Feature #10593 Signed-off-by: Raju Subramanian <rsubramanian@nicira.com> Signed-off-by: Ben Pfaff <blp@nicira.com>
		
			
				
	
	
		
			250 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
 | |
|  *
 | |
|  * 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"
 | |
| #include "vlog.h"
 | |
| 
 | |
| VLOG_DEFINE_THIS_MODULE(ovsdb_error);
 | |
| 
 | |
| 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, JSSF_SORT);
 | |
|     }
 | |
| 
 | |
|     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;
 | |
| }
 | |
| 
 | |
| /* Returns an ovsdb_error that represents an internal error for file name
 | |
|  * 'file' and line number 'line', with 'details' (formatted as with printf())
 | |
|  * as the associated message.  The caller is responsible for freeing the
 | |
|  * returned error.
 | |
|  *
 | |
|  * If 'inner_error' is nonnull then the returned error is wrapped around
 | |
|  * 'inner_error'.  Takes ownership of 'inner_error'.  */
 | |
| struct ovsdb_error *
 | |
| ovsdb_internal_error(struct ovsdb_error *inner_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)", program_name, VERSION);
 | |
| 
 | |
|     if (inner_error) {
 | |
|         char *s = ovsdb_error_to_string(inner_error);
 | |
|         ds_put_format(&ds, " (generated from: %s)", s);
 | |
|         free(s);
 | |
| 
 | |
|         ovsdb_error_destroy(inner_error);
 | |
|     }
 | |
| 
 | |
|     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;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 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",
 | |
|                                ovs_retval_to_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)", ovs_retval_to_string(error->errno_));
 | |
|     }
 | |
|     return ds_steal_cstr(&ds);
 | |
| }
 | |
| 
 | |
| const char *
 | |
| ovsdb_error_get_tag(const struct ovsdb_error *error)
 | |
| {
 | |
|     return error->tag;
 | |
| }
 | |
| 
 | |
| /* If 'error' is nonnull, logs it as an error and frees it.  To be used in
 | |
|  * situations where an error should never occur, but an 'ovsdb_error *' gets
 | |
|  * passed back anyhow. */
 | |
| void
 | |
| ovsdb_error_assert(struct ovsdb_error *error)
 | |
| {
 | |
|     if (error) {
 | |
|         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
 | |
|         char *s = ovsdb_error_to_string(error);
 | |
|         VLOG_ERR_RL(&rl, "unexpected ovsdb error: %s", s);
 | |
|         free(s);
 | |
|         ovsdb_error_destroy(error);
 | |
|     }
 | |
| }
 |