ovsdb: Improve error reporting for some internal errors.
authorBen Pfaff <blp@nicira.com>
Wed, 9 Mar 2011 20:41:37 +0000 (12:41 -0800)
committerBen Pfaff <blp@nicira.com>
Thu, 10 Mar 2011 19:23:59 +0000 (11:23 -0800)
Sometimes internal errors are generated based on an originating error.  In
these cases we were just throwing this information away.  This commit adds
this information to the internal error report so that the error will be
easier to track down.

I haven't actually seen a situation like this come up.

lib/ovsdb-error.c
lib/ovsdb-error.h
ovsdb/transaction.c

index d6b4576ea27b8b1a9685b766184af809a3fe8ec7..3b90b1616b3545c6b9e17c43b0d63f50f3006afa 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010 Nicira Networks
+/* Copyright (c) 2009, 2010, 2011 Nicira Networks
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -114,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;
@@ -144,6 +152,14 @@ ovsdb_internal_error(const char *file, int line, const char *details, ...)
 
     ds_put_format(&ds, " (%s %s%s)", program_name, VERSION, BUILDNR);
 
+    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);
index 2bff3ae563f66b440ef22dfd1ab6d4b3a95831f4..89b0c19b2966c9ec47302623dc6c09915a5b1000 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010 Nicira Networks
+/* Copyright (c) 2009, 2010, 2011 Nicira Networks
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,11 +35,25 @@ struct ovsdb_error *ovsdb_wrap_error(struct ovsdb_error *error,
                                      const char *details, ...)
     PRINTF_FORMAT(2, 3);
 
-struct ovsdb_error *ovsdb_internal_error(const char *file, int line,
+struct ovsdb_error *ovsdb_internal_error(struct ovsdb_error *error,
+                                         const char *file, int line,
                                          const char *details, ...)
-    PRINTF_FORMAT(3, 4)
+    PRINTF_FORMAT(4, 5)
     WARN_UNUSED_RESULT;
-#define OVSDB_BUG(MSG) ovsdb_internal_error(__FILE__, __LINE__, "%s", MSG)
+
+/* Returns a pointer to an ovsdb_error that represents an internal error for
+ * the current file name and line number with MSG as the associated message.
+ * The caller is responsible for freeing the internal error. */
+#define OVSDB_BUG(MSG)                                      \
+    ovsdb_internal_error(NULL, __FILE__, __LINE__, "%s", MSG)
+
+/* Returns a pointer to an ovsdb_error that represents an internal error for
+ * the current file name and line number, with MSG as the associated message.
+ * If ERROR is nonnull then the internal error is wrapped around ERROR.  Takes
+ * ownership of ERROR.  The caller is responsible for freeing the returned
+ * error. */
+#define OVSDB_WRAP_BUG(MSG, ERROR)                          \
+    ovsdb_internal_error(ERROR, __FILE__, __LINE__, "%s", MSG)
 
 void ovsdb_error_destroy(struct ovsdb_error *);
 struct ovsdb_error *ovsdb_error_clone(const struct ovsdb_error *)
index b26705a3ab2304d16c5260cb780760866c1e5690..b7c57e57ee59dbe4878c8b14baafb33170007a2e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010 Nicira Networks
+/* Copyright (c) 2009, 2010, 2011 Nicira Networks
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -218,8 +218,7 @@ update_row_ref_count(struct ovsdb_txn *txn, struct ovsdb_txn_row *r)
         if (r->old) {
             error = ovsdb_txn_adjust_row_refs(txn, r->old, column, -1);
             if (error) {
-                ovsdb_error_destroy(error);
-                return OVSDB_BUG("error decreasing refcount");
+                return OVSDB_WRAP_BUG("error decreasing refcount", error);
             }
         }
         if (r->new) {
@@ -476,8 +475,7 @@ ovsdb_txn_commit(struct ovsdb_txn *txn, bool durable)
      * was really a no-op. */
     error = for_each_txn_row(txn, determine_changes);
     if (error) {
-        ovsdb_error_destroy(error);
-        return OVSDB_BUG("can't happen");
+        return OVSDB_WRAP_BUG("can't happen", error);
     }
     if (list_is_empty(&txn->txn_tables)) {
         ovsdb_txn_abort(txn);