From patchwork Wed Sep 18 14:32:52 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 1164083 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46YQVg1Ndhz9sNf for ; Thu, 19 Sep 2019 02:32:11 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B6937C8F; Wed, 18 Sep 2019 16:31:30 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 1C044C6C for ; Wed, 18 Sep 2019 16:31:30 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 34DE976D for ; Wed, 18 Sep 2019 16:31:29 +0000 (UTC) X-Originating-IP: 66.170.99.95 Received: from localhost.localdomain (unknown [66.170.99.95]) (Authenticated sender: blp@ovn.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id E701D20006; Wed, 18 Sep 2019 16:31:26 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Wed, 18 Sep 2019 07:32:52 -0700 Message-Id: <20190918143252.3317-2-blp@ovn.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918143252.3317-1-blp@ovn.org> References: <20190918143252.3317-1-blp@ovn.org> MIME-Version: 1.0 X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH 2/2] db-ctl-base: Give better error messages for ambiguous abbreviations. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Tables and columns may be abbreviated to unique prefixes, but until now the error messages have just said there's more than one match. This commit makes the error messages list the possibilities. Signed-off-by: Ben Pfaff Reviewed-by: Yifeng Sun --- lib/db-ctl-base.c | 58 +++++++++++++++++++++++++++++----------------- tests/ovs-vsctl.at | 5 +++- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c index 3bd9f006acb1..6ae638be5a2b 100644 --- a/lib/db-ctl-base.c +++ b/lib/db-ctl-base.c @@ -430,31 +430,39 @@ static char * get_column(const struct ovsdb_idl_table_class *table, const char *column_name, const struct ovsdb_idl_column **columnp) { + struct sset best_matches = SSET_INITIALIZER(&best_matches); const struct ovsdb_idl_column *best_match = NULL; unsigned int best_score = 0; - size_t i; - for (i = 0; i < table->n_columns; i++) { + for (size_t i = 0; i < table->n_columns; i++) { const struct ovsdb_idl_column *column = &table->columns[i]; unsigned int score = score_partial_match(column->name, column_name); - if (score > best_score) { + if (score && score >= best_score) { + if (score > best_score) { + sset_clear(&best_matches); + } + sset_add(&best_matches, column->name); best_match = column; best_score = score; - } else if (score == best_score) { - best_match = NULL; } } - *columnp = best_match; - if (best_match) { - return NULL; - } else if (best_score) { - return xasprintf("%s contains more than one column whose name " - "matches \"%s\"", table->name, column_name); + char *error = NULL; + *columnp = NULL; + if (!best_match) { + error = xasprintf("%s does not contain a column whose name matches " + "\"%s\"", table->name, column_name); + } else if (sset_count(&best_matches) == 1) { + *columnp = best_match; } else { - return xasprintf("%s does not contain a column whose name matches " - "\"%s\"", table->name, column_name); + char *matches = sset_join(&best_matches, ", ", ""); + error = xasprintf("%s contains more than one column " + "whose name matches \"%s\": %s", + table->name, column_name, matches); + free(matches); } + sset_destroy(&best_matches); + return error; } static char * OVS_WARN_UNUSED_RESULT @@ -1207,27 +1215,35 @@ cmd_list(struct ctl_context *ctx) static char * OVS_WARN_UNUSED_RESULT get_table(const char *table_name, const struct ovsdb_idl_table_class **tablep) { + struct sset best_matches = SSET_INITIALIZER(&best_matches); const struct ovsdb_idl_table_class *best_match = NULL; unsigned int best_score = 0; - char *error = NULL; for (const struct ovsdb_idl_table_class *table = idl_classes; table < &idl_classes[n_classes]; table++) { unsigned int score = score_partial_match(table->name, table_name); - if (score > best_score) { + if (score && score >= best_score) { + if (score > best_score) { + sset_clear(&best_matches); + } + sset_add(&best_matches, table->name); best_match = table; best_score = score; - } else if (score == best_score) { - best_match = NULL; } } - if (best_match) { + + char *error = NULL; + if (!best_match) { + error = xasprintf("unknown table \"%s\"", table_name); + } else if (sset_count(&best_matches) == 1) { *tablep = best_match; - } else if (best_score) { - error = xasprintf("multiple table names match \"%s\"", table_name); } else { - error = xasprintf("unknown table \"%s\"", table_name); + char *matches = sset_join(&best_matches, ", ", ""); + error = xasprintf("\"%s\" matches multiple table names: %s", + table_name, matches); + free(matches); } + sset_destroy(&best_matches); return error; } diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at index 4907be35d342..1b9c6d90219d 100644 --- a/tests/ovs-vsctl.at +++ b/tests/ovs-vsctl.at @@ -848,6 +848,9 @@ targets : ["1.2.3.4:567"] AT_CHECK([RUN_OVS_VSCTL([list interx x])], [1], [], [ovs-vsctl: unknown table "interx" ]) +AT_CHECK([RUN_OVS_VSCTL([list c x])], + [1], [], [ovs-vsctl: "c" matches multiple table names: CT_Timeout_Policy, CT_Zone, Controller +]) AT_CHECK([RUN_OVS_VSCTL([list bridge x])], [1], [], [ovs-vsctl: no row "x" in table Bridge ]) @@ -855,7 +858,7 @@ AT_CHECK([RUN_OVS_VSCTL([get bridge x datapath_id])], [1], [], [ovs-vsctl: no row "x" in table Bridge ]) AT_CHECK([RUN_OVS_VSCTL([get bridge br0 d])], - [1], [], [ovs-vsctl: Bridge contains more than one column whose name matches "d" + [1], [], [ovs-vsctl: Bridge contains more than one column whose name matches "d": datapath_id, datapath_type, datapath_version ]) AT_CHECK([RUN_OVS_VSCTL([get bridge br0 x])], [1], [], [ovs-vsctl: Bridge does not contain a column whose name matches "x"