summaryrefslogtreecommitdiff
path: root/ovsdb
diff options
context:
space:
mode:
authorIlya Maximets <i.maximets@ovn.org>2021-12-19 15:09:39 +0100
committerIlya Maximets <i.maximets@ovn.org>2022-03-03 15:21:21 +0100
commita3e97b1af1bdcaa802c6caa9e73087df7077d2b1 (patch)
tree874bc2376b871a5987605eab6b7365f7d8f7ef26 /ovsdb
parent999ba294fb4f9a39db77070f0b2045bf166c2287 (diff)
downloadopenvswitch-a3e97b1af1bdcaa802c6caa9e73087df7077d2b1.tar.gz
ovsdb: relay: Add transaction history support.
Even though relays can be scaled to the big number of servers to handle a lot more clients, lack of transaction history may cause significant load if clients are re-connecting. E.g. in case of the upgrade of a large-scale OVN deployment, relays can be taken down one by one forcing all the clients of one relay to jump to other ones. And all these clients will download the database from scratch from a new relay. Since relay itself supports monitor_cond_since connection to the main cluster, it receives the last transaction id along with each update. Since these transaction ids are 'eid's of actual transactions, they can be used by relay for a transaction history. Relay may not receive all the transaction ids, because the main cluster may combine several changes into a single monitor update. However, all relays will, likely, receive same updates with the same transaction ids, so the case where transaction id can not be found after re-connection between relays should not be very common. If some id is missing on the relay (i.e. this update was merged with some other update and newer id was used) the client will just re-download the database as if there was a normal transaction history miss. OVSDB client synchronization module updated to provide the last transaction id along with the update. Relay module updated to use these ids as a transaction id. If ids are zero, relay decides that the main server doesn't support transaction ids and disables the transaction history accordingly. Using ovsdb_txn_replay_commit() instead of ovsdb_txn_propose_commit_block(), so transactions are added to the history. This can be done, because relays has no file storage, so there is no need to write anything. Relay tests modified to test both standalone and clustered database as a main server. Checks added to ensure that all servers receive the same transaction ids in monitor updates. Acked-by: Mike Pattrick <mkp@redhat.com> Acked-by: Han Zhou <hzhou@ovn.org> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'ovsdb')
-rw-r--r--ovsdb/ovsdb-server.c8
-rw-r--r--ovsdb/relay.c28
-rw-r--r--ovsdb/transaction.c9
3 files changed, 33 insertions, 12 deletions
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index 9fe90592e..b975c17fc 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -729,9 +729,11 @@ open_db(struct server_config *config, const char *filename)
db->db = ovsdb_create(schema, storage);
ovsdb_jsonrpc_server_add_db(config->jsonrpc, db->db);
- /* Enable txn history for clustered mode. It is not enabled for other mode
- * for now, since txn id is available for clustered mode only. */
- ovsdb_txn_history_init(db->db, ovsdb_storage_is_clustered(storage));
+ /* Enable txn history for clustered and relay modes. It is not enabled for
+ * other modes for now, since txn id is available for clustered and relay
+ * modes only. */
+ ovsdb_txn_history_init(db->db,
+ is_relay || ovsdb_storage_is_clustered(storage));
read_db(config, db);
diff --git a/ovsdb/relay.c b/ovsdb/relay.c
index ef0e44d34..2df393403 100644
--- a/ovsdb/relay.c
+++ b/ovsdb/relay.c
@@ -222,7 +222,8 @@ ovsdb_relay_process_row_update(struct ovsdb_table *table,
static struct ovsdb_error *
ovsdb_relay_parse_update__(struct ovsdb *db,
- const struct ovsdb_cs_db_update *du)
+ const struct ovsdb_cs_db_update *du,
+ const struct uuid *last_id)
{
struct ovsdb_error *error = NULL;
struct ovsdb_txn *txn;
@@ -254,8 +255,17 @@ exit:
ovsdb_txn_abort(txn);
return error;
} else {
- /* Commit transaction. */
- error = ovsdb_txn_propose_commit_block(txn, false);
+ if (uuid_is_zero(last_id)) {
+ /* The relay source doesn't support unique transaction ids,
+ * disabling transaction history for relay. */
+ ovsdb_txn_history_destroy(db);
+ ovsdb_txn_history_init(db, false);
+ } else {
+ ovsdb_txn_set_txnid(last_id, txn);
+ }
+ /* Commit transaction.
+ * There is no storage, so ovsdb_txn_replay_commit() can be used. */
+ error = ovsdb_txn_replay_commit(txn);
}
return error;
@@ -266,6 +276,7 @@ ovsdb_relay_clear(struct ovsdb *db)
{
struct ovsdb_txn *txn = ovsdb_txn_create(db);
struct shash_node *table_node;
+ struct ovsdb_error *error;
SHASH_FOR_EACH (table_node, &db->tables) {
struct ovsdb_table *table = table_node->data;
@@ -276,7 +287,14 @@ ovsdb_relay_clear(struct ovsdb *db)
}
}
- return ovsdb_txn_propose_commit_block(txn, false);
+ /* There is no storage, so ovsdb_txn_replay_commit() can be used. */
+ error = ovsdb_txn_replay_commit(txn);
+
+ /* Clearing the transaction history, and re-enabling it. */
+ ovsdb_txn_history_destroy(db);
+ ovsdb_txn_history_init(db, true);
+
+ return error;
}
static void
@@ -304,7 +322,7 @@ ovsdb_relay_parse_update(struct relay_ctx *ctx,
error = ovsdb_relay_clear(ctx->db);
}
if (!error) {
- error = ovsdb_relay_parse_update__(ctx->db, du);
+ error = ovsdb_relay_parse_update__(ctx->db, du, &update->last_id);
}
}
ovsdb_cs_db_update_destroy(du);
diff --git a/ovsdb/transaction.c b/ovsdb/transaction.c
index db86d847c..090068603 100644
--- a/ovsdb/transaction.c
+++ b/ovsdb/transaction.c
@@ -40,7 +40,7 @@ struct ovsdb_txn {
struct ovsdb *db;
struct ovs_list txn_tables; /* Contains "struct ovsdb_txn_table"s. */
struct ds comment;
- struct uuid txnid; /* For clustered mode only. It is the eid. */
+ struct uuid txnid; /* For clustered and relay modes. It is the eid. */
size_t n_atoms; /* Number of atoms in all transaction rows. */
ssize_t n_atoms_diff; /* Difference between number of added and
* removed atoms. */
@@ -1143,9 +1143,10 @@ ovsdb_txn_complete(struct ovsdb_txn *txn)
/* Applies 'txn' to the internal representation of the database. This is for
* transactions that don't need to be written to storage; probably, they came
- * from storage. These transactions shouldn't ordinarily fail because storage
- * should contain only consistent transactions. (One exception is for database
- * conversion in ovsdb_convert().) */
+ * from storage or from relay. These transactions shouldn't ordinarily fail
+ * because storage should contain only consistent transactions. (One exception
+ * is for database conversion in ovsdb_convert().) Transactions from relay
+ * should also be consistent, since relay source should have verified them. */
struct ovsdb_error * OVS_WARN_UNUSED_RESULT
ovsdb_txn_replay_commit(struct ovsdb_txn *txn)
{