ofproto: Fix potential leak during flow mods.
[sliver-openvswitch.git] / lib / ovsdb-error.c
index c922149..eb9f1ee 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010 Nicira Networks
+/* 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.
@@ -25,8 +25,7 @@
 #include "util.h"
 #include "vlog.h"
 
-#define THIS_MODULE VLM_ovsdb_error
-#include "vlog.h"
+VLOG_DEFINE_THIS_MODULE(ovsdb_error);
 
 struct ovsdb_error {
     const char *tag;            /* String for "error" member. */
@@ -87,7 +86,7 @@ ovsdb_syntax_error(const struct json *json, const char *tag,
 
     if (json) {
         /* XXX this is much too much information in some cases */
-        error->syntax = json_to_string(json, 0);
+        error->syntax = json_to_string(json, JSSF_SORT);
     }
 
     return error;
@@ -115,8 +114,16 @@ ovsdb_wrap_error(struct ovsdb_error *error, const char *details, ...)
     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(const char *file, int line, const char *details, ...)
+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;
@@ -143,7 +150,15 @@ ovsdb_internal_error(const char *file, int line, const char *details, ...)
         ds_put_char(&ds, ')');
     }
 
-    ds_put_format(&ds, " (%s %s%s)", program_name, VERSION, BUILDNR);
+    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));
 
@@ -177,12 +192,6 @@ ovsdb_error_clone(const struct ovsdb_error *old)
     }
 }
 
-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)
 {
@@ -196,7 +205,7 @@ ovsdb_error_to_json(const struct ovsdb_error *error)
     }
     if (error->errno_) {
         json_object_put_string(json, "io-error",
-                               ovsdb_errno_string(error->errno_));
+                               ovs_retval_to_string(error->errno_));
     }
     return json;
 }
@@ -213,7 +222,7 @@ ovsdb_error_to_string(const struct ovsdb_error *error)
         ds_put_format(&ds, ": %s", error->details);
     }
     if (error->errno_) {
-        ds_put_format(&ds, " (%s)", ovsdb_errno_string(error->errno_));
+        ds_put_format(&ds, " (%s)", ovs_retval_to_string(error->errno_));
     }
     return ds_steal_cstr(&ds);
 }
@@ -238,4 +247,3 @@ ovsdb_error_assert(struct ovsdb_error *error)
         ovsdb_error_destroy(error);
     }
 }
-