get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1528932/
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1528932,
    "url": "http://patchwork.ozlabs.org/api/patches/1528932/",
    "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/20210916153753.20400-1-dceara@redhat.com/",
    "project": {
        "id": 47,
        "url": "http://patchwork.ozlabs.org/api/projects/47/",
        "name": "Open vSwitch",
        "link_name": "openvswitch",
        "list_id": "ovs-dev.openvswitch.org",
        "list_email": "ovs-dev@openvswitch.org",
        "web_url": "http://openvswitch.org/",
        "scm_url": "git@github.com:openvswitch/ovs.git",
        "webscm_url": "https://github.com/openvswitch/ovs",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20210916153753.20400-1-dceara@redhat.com>",
    "list_archive_url": null,
    "date": "2021-09-16T15:37:53",
    "name": "[ovs-dev,v2] ovsdb-server: Log database transactions for user requested tables.",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "4226c17983ab49ceeca5f48c26a6e875e76b0169",
    "submitter": {
        "id": 76591,
        "url": "http://patchwork.ozlabs.org/api/people/76591/",
        "name": "Dumitru Ceara",
        "email": "dceara@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/20210916153753.20400-1-dceara@redhat.com/mbox/",
    "series": [
        {
            "id": 262657,
            "url": "http://patchwork.ozlabs.org/api/series/262657/",
            "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=262657",
            "date": "2021-09-16T15:37:53",
            "name": "[ovs-dev,v2] ovsdb-server: Log database transactions for user requested tables.",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/262657/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1528932/comments/",
    "check": "success",
    "checks": "http://patchwork.ozlabs.org/api/patches/1528932/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<ovs-dev-bounces@openvswitch.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "dev@openvswitch.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@ozlabs.org",
            "ovs-dev@lists.linuxfoundation.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=QVttiftH;\n\tdkim-atps=neutral",
            "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.137; helo=smtp4.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN>)",
            "smtp2.osuosl.org (amavisd-new);\n dkim=fail (1024-bit key) reason=\"fail (body has been altered)\"\n header.d=redhat.com",
            "relay.mimecast.com;\n auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=dceara@redhat.com"
        ],
        "Received": [
            "from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 4H9Lnw4nHVz9sR4\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 17 Sep 2021 01:38:12 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id EF228415B9;\n\tThu, 16 Sep 2021 15:38:09 +0000 (UTC)",
            "from smtp4.osuosl.org ([127.0.0.1])\n\tby localhost (smtp4.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 0Q4U3sRx6imC; Thu, 16 Sep 2021 15:38:08 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp4.osuosl.org (Postfix) with ESMTPS id F105A415AE;\n\tThu, 16 Sep 2021 15:38:07 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id CE8F3C0011;\n\tThu, 16 Sep 2021 15:38:07 +0000 (UTC)",
            "from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id CC882C000D\n for <dev@openvswitch.org>; Thu, 16 Sep 2021 15:38:06 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id B221940227\n for <dev@openvswitch.org>; Thu, 16 Sep 2021 15:38:06 +0000 (UTC)",
            "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id 3SDHuVrseP3H for <dev@openvswitch.org>;\n Thu, 16 Sep 2021 15:38:05 +0000 (UTC)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [216.205.24.124])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 42D774020E\n for <dev@openvswitch.org>; Thu, 16 Sep 2021 15:38:05 +0000 (UTC)",
            "from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com\n [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id\n us-mta-323-zo7ua3k6N9GB9mP9yJL00g-1; Thu, 16 Sep 2021 11:38:00 -0400",
            "from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com\n [10.5.11.14])\n (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n (No client certificate requested)\n by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E76DE101F7B0;\n Thu, 16 Sep 2021 15:37:58 +0000 (UTC)",
            "from dceara.remote.csb (unknown [10.39.193.243])\n by smtp.corp.redhat.com (Postfix) with ESMTP id 7ED8A5D9CA;\n Thu, 16 Sep 2021 15:37:57 +0000 (UTC)"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.8.0",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1631806684;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding;\n bh=t/r2Z87+gmpFA6OFcyJkWhZXARt6w1DVdis4nVyZv60=;\n b=QVttiftHhrVFFWpGj2dqwrpSKirZeQ1PQNrf1Bk9oer2Asu6jnSvTBw/ceos5IFDXZN5ew\n Z2mwaj8Mh1AvfLr5VP5afmI/d56U7JlMuXMQuGroXJrPtpg5vPlUJYxIuHNzyxGETXqT58\n 1gJLdu7tKJJCFkh2es8FE9U4Bkd+9X8=",
        "X-MC-Unique": "zo7ua3k6N9GB9mP9yJL00g-1",
        "From": "Dumitru Ceara <dceara@redhat.com>",
        "To": "dev@openvswitch.org",
        "Date": "Thu, 16 Sep 2021 17:37:53 +0200",
        "Message-Id": "<20210916153753.20400-1-dceara@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 2.79 on 10.5.11.14",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Cc": "i.maximets@ovn.org",
        "Subject": "[ovs-dev] [PATCH v2] ovsdb-server: Log database transactions for\n\tuser requested tables.",
        "X-BeenThere": "ovs-dev@openvswitch.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "<ovs-dev.openvswitch.org>",
        "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>",
        "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>",
        "List-Post": "<mailto:ovs-dev@openvswitch.org>",
        "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>",
        "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "ovs-dev-bounces@openvswitch.org",
        "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>"
    },
    "content": "Add a new command, 'ovsdb-server/log-db-ops DB TABLE on|off', which\nallows the user to enable/disable transaction logging for specific\ndatabases and tables.\n\nBy default, logging is disabled.  Once enabled, logs are generated\nwith level INFO and are also rate limited.\n\nIf used with care, this command can be useful in analyzing production\ndeployment performance issues, allowing the user to pin point\nbottlenecks without the need to enable wider debug logs, e.g., jsonrpc.\n\nSigned-off-by: Dumitru Ceara <dceara@redhat.com>\n---\nA sample use case is an ovn-kubernetes scaled deployment in which\nwe're interesting in reducing time to bring up PODs (represented by\nOVN logical switch ports).  In order to determine exactly where the\nbottleneck is when provisioning PODs (CMS/ovn-nbctl/client\nIDLs/ovsdb-server/ovn-controller/etc) we need timestamps of when\noperations happen at various places in the stack.\n\nWithout this patch the only option for tracking when transactions\nhappen in the Northbound database is to enable jsonrpc debug logs in\novsdb-server.  This generates a rather large amount of data.\n\nInstead, now, users would be able to just enable logging for the\nLogical_Switch_Port table getting more relevant and precise\ninformation.\n\nV2:\n- rebased (fixed conflicts in NEWS).\n---\n NEWS                 |  4 ++++\n ovsdb/ovsdb-server.c | 38 +++++++++++++++++++++++++++++++++\n ovsdb/row.c          | 17 +++++++++++++++\n ovsdb/row.h          |  1 +\n ovsdb/table.c        |  7 ++++++\n ovsdb/table.h        |  3 +++\n ovsdb/transaction.c  | 51 ++++++++++++++++++++++++++++++++++++++++++++\n 7 files changed, 121 insertions(+)",
    "diff": "diff --git a/NEWS b/NEWS\nindex 90f4b15902b8..d56329772276 100644\n--- a/NEWS\n+++ b/NEWS\n@@ -10,6 +10,10 @@ Post-v2.16.0\n        limiting behavior.\n      * Add hardware offload support for matching IPv4/IPv6 frag types\n        (experimental).\n+   - OVSDB:\n+     * New unixctl command 'ovsdb-server/log-db-ops DB TABLE on|off\".\n+       If turned on, ovsdb-server will log (at level INFO and rate limited)\n+       all operations that are committed to table TABLE in the DB database.\n \n \n v2.16.0 - 16 Aug 2021\ndiff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c\nindex 0b3d2bb71432..c48645f7e255 100644\n--- a/ovsdb/ovsdb-server.c\n+++ b/ovsdb/ovsdb-server.c\n@@ -115,6 +115,7 @@ static unixctl_cb_func ovsdb_server_list_remotes;\n static unixctl_cb_func ovsdb_server_add_database;\n static unixctl_cb_func ovsdb_server_remove_database;\n static unixctl_cb_func ovsdb_server_list_databases;\n+static unixctl_cb_func ovsdb_server_log_db_ops;\n \n static void read_db(struct server_config *, struct db *);\n static struct ovsdb_error *open_db(struct server_config *,\n@@ -443,6 +444,8 @@ main(int argc, char *argv[])\n                              ovsdb_server_remove_database, &server_config);\n     unixctl_command_register(\"ovsdb-server/list-dbs\", \"\", 0, 0,\n                              ovsdb_server_list_databases, &all_dbs);\n+    unixctl_command_register(\"ovsdb-server/log-db-ops\", \"DB TABLE on|off\",\n+                             3, 3, ovsdb_server_log_db_ops, &all_dbs);\n     unixctl_command_register(\"ovsdb-server/perf-counters-show\", \"\", 0, 0,\n                              ovsdb_server_perf_counters_show, NULL);\n     unixctl_command_register(\"ovsdb-server/perf-counters-clear\", \"\", 0, 0,\n@@ -1769,6 +1772,41 @@ ovsdb_server_list_databases(struct unixctl_conn *conn, int argc OVS_UNUSED,\n     ds_destroy(&s);\n }\n \n+static void\n+ovsdb_server_log_db_ops(struct unixctl_conn *conn, int argc OVS_UNUSED,\n+                        const char *argv[], void *all_dbs_)\n+{\n+    struct shash *all_dbs = all_dbs_;\n+    const char *db_name = argv[1];\n+    const char *tbl_name = argv[2];\n+    const char *command = argv[3];\n+    bool log;\n+\n+    if (!strcmp(command, \"on\")) {\n+        log = true;\n+    } else if (!strcmp(command, \"off\")) {\n+        log = false;\n+    } else {\n+        unixctl_command_reply_error(conn, \"invalid argument\");\n+        return;\n+    }\n+\n+    struct db *db = shash_find_data(all_dbs, db_name);\n+    if (!db) {\n+        unixctl_command_reply_error(conn, \"no such database\");\n+        return;\n+    }\n+\n+    struct ovsdb_table *table = ovsdb_get_table(db->db, tbl_name);\n+    if (!table) {\n+        unixctl_command_reply_error(conn, \"no such table\");\n+        return;\n+    }\n+\n+    ovsdb_table_log_ops(table, log);\n+    unixctl_command_reply(conn, NULL);\n+}\n+\n static void\n ovsdb_server_get_sync_status(struct unixctl_conn *conn, int argc OVS_UNUSED,\n                              const char *argv[] OVS_UNUSED, void *config_)\ndiff --git a/ovsdb/row.c b/ovsdb/row.c\nindex 65a0546211c8..5e31716506bc 100644\n--- a/ovsdb/row.c\n+++ b/ovsdb/row.c\n@@ -278,6 +278,23 @@ ovsdb_row_to_json(const struct ovsdb_row *row,\n     }\n     return json;\n }\n+\n+void\n+ovsdb_row_to_string(const struct ovsdb_row *row, struct ds *out)\n+{\n+    struct shash_node *node;\n+\n+    SHASH_FOR_EACH (node, &row->table->schema->columns) {\n+        const struct ovsdb_column *column = node->data;\n+\n+        ds_put_format(out, \"%s:\", column->name);\n+        ovsdb_datum_to_string(&row->fields[column->index], &column->type, out);\n+        ds_put_cstr(out, \",\");\n+    }\n+    if (shash_count(&row->table->schema->columns)) {\n+        ds_chomp(out, ',');\n+    }\n+}\n \f\n void\n ovsdb_row_set_init(struct ovsdb_row_set *set)\ndiff --git a/ovsdb/row.h b/ovsdb/row.h\nindex 394ac8eb49b6..f22a08ecd197 100644\n--- a/ovsdb/row.h\n+++ b/ovsdb/row.h\n@@ -95,6 +95,7 @@ struct ovsdb_error *ovsdb_row_from_json(struct ovsdb_row *,\n     OVS_WARN_UNUSED_RESULT;\n struct json *ovsdb_row_to_json(const struct ovsdb_row *,\n                                const struct ovsdb_column_set *include);\n+void ovsdb_row_to_string(const struct ovsdb_row *, struct ds *);\n \n static inline const struct uuid *\n ovsdb_row_get_uuid(const struct ovsdb_row *row)\ndiff --git a/ovsdb/table.c b/ovsdb/table.c\nindex 455a3663fe89..b7b41d139914 100644\n--- a/ovsdb/table.c\n+++ b/ovsdb/table.c\n@@ -301,10 +301,17 @@ ovsdb_table_create(struct ovsdb_table_schema *ts)\n         hmap_init(&table->indexes[i]);\n     }\n     hmap_init(&table->rows);\n+    table->log = false;\n \n     return table;\n }\n \n+void\n+ovsdb_table_log_ops(struct ovsdb_table *table, bool enabled)\n+{\n+    table->log = enabled;\n+}\n+\n void\n ovsdb_table_destroy(struct ovsdb_table *table)\n {\ndiff --git a/ovsdb/table.h b/ovsdb/table.h\nindex ce69a5d130bf..be88b7a59279 100644\n--- a/ovsdb/table.h\n+++ b/ovsdb/table.h\n@@ -63,10 +63,13 @@ struct ovsdb_table {\n      * ovsdb_row\"s.  Each of the hmap_nodes in indexes[i] are at index 'i' at\n      * the end of struct ovsdb_row, following the 'fields' member. */\n     struct hmap *indexes;\n+\n+    bool log; /* True if logging is enabled for this table. */\n };\n \n struct ovsdb_table *ovsdb_table_create(struct ovsdb_table_schema *);\n void ovsdb_table_destroy(struct ovsdb_table *);\n+void ovsdb_table_log_ops(struct ovsdb_table *, bool);\n \n const struct ovsdb_row *ovsdb_table_get_row(const struct ovsdb_table *,\n                                             const struct uuid *);\ndiff --git a/ovsdb/transaction.c b/ovsdb/transaction.c\nindex 8ffefcf7c9d0..dc07e9c00a4b 100644\n--- a/ovsdb/transaction.c\n+++ b/ovsdb/transaction.c\n@@ -29,6 +29,7 @@\n #include \"openvswitch/vlog.h\"\n #include \"ovsdb-error.h\"\n #include \"ovsdb.h\"\n+#include \"ovs-thread.h\"\n #include \"row.h\"\n #include \"storage.h\"\n #include \"table.h\"\n@@ -95,6 +96,7 @@ struct ovsdb_txn_row {\n static struct ovsdb_error * OVS_WARN_UNUSED_RESULT\n delete_garbage_row(struct ovsdb_txn *txn, struct ovsdb_txn_row *r);\n static void ovsdb_txn_row_prefree(struct ovsdb_txn_row *);\n+static void ovsdb_txn_row_log(const struct ovsdb_txn_row *);\n static struct ovsdb_error * OVS_WARN_UNUSED_RESULT\n for_each_txn_row(struct ovsdb_txn *txn,\n                       struct ovsdb_error *(*)(struct ovsdb_txn *,\n@@ -104,6 +106,11 @@ for_each_txn_row(struct ovsdb_txn *txn,\n  * processed.  */\n static unsigned int serial;\n \n+/* Used by ovsdb_txn_row_log() to avoid reallocating dynamic strings\n+ * every time a row operation is logged.\n+ */\n+DEFINE_STATIC_PER_THREAD_DATA(struct ds, row_log_str, DS_EMPTY_INITIALIZER);\n+\n struct ovsdb_txn *\n ovsdb_txn_create(struct ovsdb *db)\n {\n@@ -422,6 +429,49 @@ update_ref_counts(struct ovsdb_txn *txn)\n     return for_each_txn_row(txn, check_ref_count);\n }\n \n+static void\n+ovsdb_txn_row_log(const struct ovsdb_txn_row *txn_row)\n+{\n+    static struct vlog_rate_limit rl_insert = VLOG_RATE_LIMIT_INIT(30, 60);\n+    static struct vlog_rate_limit rl_update = VLOG_RATE_LIMIT_INIT(30, 60);\n+    static struct vlog_rate_limit rl_delete = VLOG_RATE_LIMIT_INIT(30, 60);\n+\n+    if (!txn_row->table->log) {\n+        return;\n+    }\n+\n+    size_t n_columns = shash_count(&txn_row->table->schema->columns);\n+    struct ovsdb_row *log_row;\n+    const char *op = NULL;\n+\n+    if (!txn_row->old && txn_row->new) {\n+        if (!vlog_should_drop(&this_module, VLL_INFO, &rl_insert)) {\n+            log_row = txn_row->new;\n+            op = \"inserted\";\n+        }\n+    } else if (txn_row->old && txn_row->new\n+               && !bitmap_is_all_zeros(txn_row->changed, n_columns)) {\n+        if (!vlog_should_drop(&this_module, VLL_INFO, &rl_update)) {\n+            log_row = txn_row->new;\n+            op = \"updated\";\n+        }\n+    } else if (txn_row->old && !txn_row->new) {\n+        if (!vlog_should_drop(&this_module, VLL_INFO, &rl_delete)) {\n+            log_row = txn_row->old;\n+            op = \"deleted\";\n+        }\n+    }\n+\n+    if (op) {\n+        struct ds *ds = row_log_str_get();\n+        ds_clear(ds);\n+        ds_put_format(ds, \"table:%s,op:%s,\", txn_row->table->schema->name,\n+                      op);\n+        ovsdb_row_to_string(log_row, ds);\n+        VLOG_INFO(\"%s\", ds_cstr(ds));\n+    }\n+}\n+\n static struct ovsdb_error *\n ovsdb_txn_row_commit(struct ovsdb_txn *txn OVS_UNUSED,\n                      struct ovsdb_txn_row *txn_row)\n@@ -445,6 +495,7 @@ ovsdb_txn_row_commit(struct ovsdb_txn *txn OVS_UNUSED,\n         }\n     }\n \n+    ovsdb_txn_row_log(txn_row);\n     ovsdb_txn_row_prefree(txn_row);\n     if (txn_row->new) {\n         txn_row->new->n_refs = txn_row->n_refs;\n",
    "prefixes": [
        "ovs-dev",
        "v2"
    ]
}