revalidator: Fix ukey stats cache updating.
[sliver-openvswitch.git] / lib / table.c
index d150b29..4628170 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include "table.h"
 
-#include <assert.h>
-
 #include "dynamic-string.h"
 #include "json.h"
 #include "ovsdb-data.h"
+#include "ovsdb-error.h"
+#include "timeval.h"
 #include "util.h"
 
 struct column {
@@ -36,7 +36,7 @@ cell_to_text(struct cell *cell, const struct table_style *style)
         if (cell->json) {
             if (style->cell_format == CF_JSON || !cell->type) {
                 cell->text = json_to_string(cell->json, JSSF_SORT);
-            } else if (style->cell_format == CF_STRING) {
+            } else {
                 struct ovsdb_datum datum;
                 struct ovsdb_error *error;
                 struct ds s;
@@ -45,14 +45,17 @@ cell_to_text(struct cell *cell, const struct table_style *style)
                                               NULL);
                 if (!error) {
                     ds_init(&s);
-                    ovsdb_datum_to_string(&datum, cell->type, &s);
+                    if (style->cell_format == CF_STRING) {
+                        ovsdb_datum_to_string(&datum, cell->type, &s);
+                    } else {
+                        ovsdb_datum_to_bare(&datum, cell->type, &s);
+                    }
                     ovsdb_datum_destroy(&datum, cell->type);
                     cell->text = ds_steal_cstr(&s);
                 } else {
                     cell->text = json_to_string(cell->json, JSSF_SORT);
+                    ovsdb_error_destroy(error);
                 }
-            } else {
-                NOT_REACHED();
             }
         } else {
             cell->text = xstrdup("");
@@ -119,6 +122,14 @@ table_set_caption(struct table *table, char *caption)
     table->caption = caption;
 }
 
+/* Turns printing a timestamp along with 'table' on or off, according to
+ * 'timestamp'.  */
+void
+table_set_timestamp(struct table *table, bool timestamp)
+{
+    table->timestamp = timestamp;
+}
+
 /* Adds a new column to 'table' just to the right of any existing column, with
  * 'heading' as a title for the column.  'heading' must be a valid printf()
  * format specifier.
@@ -130,7 +141,7 @@ table_add_column(struct table *table, const char *heading, ...)
     struct column *column;
     va_list args;
 
-    assert(!table->n_rows);
+    ovs_assert(!table->n_rows);
     if (table->n_columns >= table->allocated_columns) {
         table->columns = x2nrealloc(table->columns, &table->allocated_columns,
                                     sizeof *table->columns);
@@ -191,8 +202,8 @@ table_add_cell(struct table *table)
 {
     size_t x, y;
 
-    assert(table->n_rows > 0);
-    assert(table->current_column < table->n_columns);
+    ovs_assert(table->n_rows > 0);
+    ovs_assert(table->current_column < table->n_columns);
 
     x = table->current_column++;
     y = table->n_rows - 1;
@@ -207,6 +218,22 @@ table_print_table_line__(struct ds *line)
     ds_clear(line);
 }
 
+static char *
+table_format_timestamp__(void)
+{
+    return xastrftime_msec("%Y-%m-%d %H:%M:%S.###", time_wall_msec(), true);
+}
+
+static void
+table_print_timestamp__(const struct table *table)
+{
+    if (table->timestamp) {
+        char *s = table_format_timestamp__();
+        puts(s);
+        free(s);
+    }
+}
+
 static void
 table_print_table__(const struct table *table, const struct table_style *style)
 {
@@ -219,6 +246,8 @@ table_print_table__(const struct table *table, const struct table_style *style)
         putchar('\n');
     }
 
+    table_print_timestamp__(table);
+
     if (table->caption) {
         puts(table->caption);
     }
@@ -272,6 +301,36 @@ table_print_table__(const struct table *table, const struct table_style *style)
     free(widths);
 }
 
+static void
+table_print_list__(const struct table *table, const struct table_style *style)
+{
+    static int n = 0;
+    size_t x, y;
+
+    if (n++ > 0) {
+        putchar('\n');
+    }
+
+    table_print_timestamp__(table);
+
+    if (table->caption) {
+        puts(table->caption);
+    }
+
+    for (y = 0; y < table->n_rows; y++) {
+        if (y > 0) {
+            putchar('\n');
+        }
+        for (x = 0; x < table->n_columns; x++) {
+            const char *text = cell_to_text(table_cell__(table, y, x), style);
+            if (style->headings) {
+                printf("%-20s: ", table->columns[x].heading);
+            }
+            puts(text);
+        }
+    }
+}
+
 static void
 table_escape_html_text__(const char *s, size_t n)
 {
@@ -325,6 +384,8 @@ table_print_html__(const struct table *table, const struct table_style *style)
 {
     size_t x, y;
 
+    table_print_timestamp__(table);
+
     fputs("<table border=1>\n", stdout);
 
     if (table->caption) {
@@ -395,6 +456,8 @@ table_print_csv__(const struct table *table, const struct table_style *style)
         putchar('\n');
     }
 
+    table_print_timestamp__(table);
+
     if (table->caption) {
         puts(table->caption);
     }
@@ -433,6 +496,11 @@ table_print_json__(const struct table *table, const struct table_style *style)
     if (table->caption) {
         json_object_put_string(json, "caption", table->caption);
     }
+    if (table->timestamp) {
+        char *s = table_format_timestamp__();
+        json_object_put_string(json, "time", s);
+        free(s);
+    }
 
     headings = json_array_create_empty();
     for (x = 0; x < table->n_columns; x++) {
@@ -448,8 +516,10 @@ table_print_json__(const struct table *table, const struct table_style *style)
             const struct cell *cell = table_cell__(table, y, x);
             if (cell->text) {
                 json_array_add(row, json_string_create(cell->text));
-            } else {
+            } else if (cell->json) {
                 json_array_add(row, json_clone(cell->json));
+            } else {
+                json_array_add(row, json_null_create());
             }
         }
         json_array_add(data, row);
@@ -469,6 +539,8 @@ table_parse_format(struct table_style *style, const char *format)
 {
     if (!strcmp(format, "table")) {
         style->format = TF_TABLE;
+    } else if (!strcmp(format, "list")) {
+        style->format = TF_LIST;
     } else if (!strcmp(format, "html")) {
         style->format = TF_HTML;
     } else if (!strcmp(format, "csv")) {
@@ -487,6 +559,8 @@ table_parse_cell_format(struct table_style *style, const char *format)
 {
     if (!strcmp(format, "string")) {
         style->cell_format = CF_STRING;
+    } else if (!strcmp(format, "bare")) {
+        style->cell_format = CF_BARE;
     } else if (!strcmp(format, "json")) {
         style->cell_format = CF_JSON;
     } else {
@@ -503,6 +577,10 @@ table_print(const struct table *table, const struct table_style *style)
         table_print_table__(table, style);
         break;
 
+    case TF_LIST:
+        table_print_list__(table, style);
+        break;
+
     case TF_HTML:
         table_print_html__(table, style);
         break;