On Sun, 2021-12-19 at 15:09 +0100, Ilya Maximets wrote:
> If a single transaction exceeds the size of the whole database (e.g.,
> a lot of rows got removed and new ones added), transaction history
> will
> be drained.  This leads to sending UUID_ZERO to the clients as the
> last
> transaction id in the next monitor update, because monitor doesn't
> know what was the actual last transaction id.  In case of a re-
> connect
> that will cause re-downloading of the whole database, since the
> client's last_id will be out of sync.
> 
> One solution would be to store the last transaction ID separately
> from the actual transactions, but that will require a careful
> management in cases where database gets reset and the history needs
> to be cleared.  Keeping the one last transaction instead to avoid
> the problem.  That should not be a big concern in terms of memory
> consumption, because this last transaction will be removed from the
> history once the next transaction appeared.  This is also not a
> concern
> for a fast re-sync, because this last transaction will not be used
> for the monitor reply; it's either client already has it, so no need
> to send, or it's a history miss.
> 
> The test updated to not check the number of atoms if there is only
> one transaction in the history.
> 
> Fixes: 317b1bfd7dd3 ("ovsdb: Don't let transaction history grow
> larger than the database.")
> Signed-off-by: Ilya Maximets <[email protected]>
> ---
>  ovsdb/transaction.c   |  6 ++++--
>  tests/ovsdb-server.at | 16 +++++++++-------
>  2 files changed, 13 insertions(+), 9 deletions(-)
> 


Acked-by: Mike Pattrick <[email protected]>

> diff --git a/ovsdb/transaction.c b/ovsdb/transaction.c
> index 88e052800..db86d847c 100644
> --- a/ovsdb/transaction.c
> +++ b/ovsdb/transaction.c
> @@ -1595,8 +1595,10 @@ ovsdb_txn_history_run(struct ovsdb *db)
>      /* Remove old histories to limit the size of the
> history.  Removing until
>       * the number of ovsdb atoms in history becomes less than the
> number of
>       * atoms in the database, because it will be faster to just get
> a database
> -     * snapshot than re-constructing changes from the history that
> big. */
> -    while (db->n_txn_history &&
> +     * snapshot than re-constructing changes from the history that
> big.
> +     * Keeping at least one transaction to avoid sending UUID_ZERO
> as a last id
> +     * if all entries got removed due to the size limit. */
> +    while (db->n_txn_history > 1 &&
>             (db->n_txn_history > 100 ||
>              db->n_txn_history_atoms > db->n_atoms)) {
>          struct ovsdb_txn_history_node *txn_h_node = CONTAINER_OF(
> diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at
> index 2b742f78b..876cb836c 100644
> --- a/tests/ovsdb-server.at
> +++ b/tests/ovsdb-server.at
> @@ -1250,10 +1250,11 @@ dnl the total database size, so the
> transaction history will not be able
>  dnl to hold all of them.
>  dnl
>  dnl The test verifies that the number of atoms in the transaction
> history
> -dnl is always less than the number of atoms in the database.
> -get_n_atoms () {
> +dnl is always less than the number of atoms in the database, except
> for
> +dnl a case where there is only one transaction in a history.
> +get_memory_value () {
>      n=$(ovs-appctl -t ovsdb-server memory/show dnl
> -            | tr ' ' '\n' | grep atoms | grep "^$1:" | cut -d ':' -f
> 2)
> +            | tr ' ' '\n' | grep "^$1:" | cut -d ':' -f 2)
>      if test X"$n" == "X"; then
>          n=0
>      fi
> @@ -1261,8 +1262,9 @@ get_n_atoms () {
>  }
>  
>  check_atoms () {
> -    n_db_atoms=$(get_n_atoms atoms)
> -    n_txn_history_atoms=$(get_n_atoms txn-history-atoms)
> +    if test $(get_memory_value txn-history) -eq 1; then return; fi
> +    n_db_atoms=$(get_memory_value atoms)
> +    n_txn_history_atoms=$(get_memory_value txn-history-atoms)
>      echo "n_db_atoms:          $n_db_atoms"
>      echo "n_txn_history_atoms: $n_txn_history_atoms"
>      AT_CHECK([test $n_txn_history_atoms -le $n_db_atoms])
> @@ -1274,7 +1276,7 @@ add_ports () {
>      done
>  }
>  
> -initial_db_atoms=$(get_n_atoms atoms)
> +initial_db_atoms=$(get_memory_value atoms)
>  
>  for i in $(seq 1 100); do
>      cmd=$(add_ports $i $(($i / 4 + 1)))
> @@ -1289,7 +1291,7 @@ done
>  
>  dnl After removing all the bridges, the number of atoms in the
> database
>  dnl should return to its initial value.
> -AT_CHECK([test $(get_n_atoms atoms) -eq $initial_db_atoms])
> +AT_CHECK([test $(get_memory_value atoms) -eq $initial_db_atoms])
>  
>  OVS_APP_EXIT_AND_WAIT([ovsdb-server])
>  AT_CLEANUP

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to