On 2/18/26 7:34 PM, Alexandra Rukomoinikova wrote:
> Currently, when row is inserted, we don't reparse its backrefs at once.
> Instead, we add it to the 'rows_to_reparse' list - these backreference
> links will be processed only after all updates are complete in current IDL 
> run.
> 
> Therefore, deleting records at the same run they were inserted may cause 
> problems,

Hi, Alexandra.  Thanks for working on this and sorry for delay.

> there are 3 options for significant cases
> 1. update1:
>         table A - insert
>         table B refA- insert

nit:  There are tabs and spaces mixed here.  Should just use spaces.
Also, it's better to limit the line lenght in commit messages to 72,
so it fits into 80 when displayed with 'git log'.

>    update2:
>         table A - delete
>         table B - delete
> 
> Table B would have been deleted without errors, since A already existed in 
> memory

nit: *Row in the table B
Same for the other text in the commit message.

> at the time of B's row creation and parsing.
> 
> 2. update1:
>         table B refA- insert
>         table A - insert
>    update2:
>         table B - delete
>         table A - delete
> 
> In this case B would have been deleted without any problems because B was 
> added
> to rows_to_reparse and was reparsed before deletion, thanks to commit [0]
> 
> There was an overlooked scenario where the table processing order could shift
> during updates, for example:
> update1:
>                table B refA- insert
>                table A - insert
> update2:
>                table A - delete
>                table B - delete
> In this case deleting B would trigger B.ref_a=[]
> 
> IDL process tables in the order they appear in the JSON object, i.e., in the 
> order
> they appear in the hash table. This means that different table processing 
> orders can
> occur in updates when resizing the table's hash. Currently, this corresponds 
> to
> inserting 4 → 8 → 16 elements.
> 
> In [1], a solution was proposed to not perform all deletions at once,
> but to submit them for further processing after all inserts backers reparsed,
> and then perform the deletions (without changing the logic of untracked 
> deletions).
> 
> To reproduce this situation, test was added that inserts more than 8 tables
> in the first update, and deletes only necessary rows in the second update.

May be good to mention that the test depends on the hashing order, i.e.
the hashing function, so it may not fail depending on the compiler flags
or CPU architecture.  It fails for me only if I build with -msse4.2.

> 
> [0] 
> https://github.com/openvswitch/ovs/commit/02f31a1262fccab21d6ef2726a8ac877a07a7e06

nit: Use the same format as for the Fixes tag instead of a link.

> [1] https://mail.openvswitch.org/pipermail/ovs-dev/2023-July/406152.html
> 
> Fixes: 02f31a1262fc ("ovsdb-idl: Preserve references for rows deleted in same 
> IDL run as their insertion.")

Shouldn't this be the previous commit instead:
  7b8aeadd60c8 ("ovsdb-idl: Re-parse backrefs of inserted rows only once.")
?

> 
> Signed-off-by: Alexandra Rukomoinikova <[email protected]>
> ---
>  lib/ovsdb-idl-provider.h |   1 +
>  lib/ovsdb-idl.c          |  60 ++++++++++----
>  tests/idltest.ovsschema  |  26 +++++++
>  tests/ovsdb-idl.at       | 164 ++++++++++++++++++++++++++++-----------
>  tests/test-ovsdb.c       |  51 ++++++++++++
>  tests/test-ovsdb.py      |   2 +
>  6 files changed, 246 insertions(+), 58 deletions(-)
> 
> diff --git a/lib/ovsdb-idl-provider.h b/lib/ovsdb-idl-provider.h
> index 6cf32fb50..fcb8725ae 100644
> --- a/lib/ovsdb-idl-provider.h
> +++ b/lib/ovsdb-idl-provider.h
> @@ -76,6 +76,7 @@ struct ovsdb_idl_row {
>      struct ovsdb_datum *old_datum; /* Committed data (null if orphaned). */
>      bool persist_uuid;          /* Persist 'uuid' during insert txn if set. 
> */
>      bool parsed; /* Whether the row is parsed. */
> +    struct ovs_list pending_deletion_node;

Need a comment for this one explaining what this node is for.
But also, can we use the track_node for this?  These rows must
not be tracked until the deletion and they also must not be
queued for re-parsing via 'deleted_untracked_rows' either until
the deletion is processed.

The comment for track_node is generic enough to fit the delayed
deletion use case.

>      struct ovs_list reparse_node; /* Rows that needs to be re-parsed due to
>                                     * insertion of a referenced row. */
>  
> diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
> index d8094458d..c00245f92 100644
> --- a/lib/ovsdb-idl.c
> +++ b/lib/ovsdb-idl.c
> @@ -93,6 +93,9 @@ struct ovsdb_idl {
>      struct ovsdb_idl_txn *txn;
>      struct hmap outstanding_txns;
>      bool verify_write_only;
> +    struct ovs_list pending_deletions_rows; /* Stores rows deleted in the

s/pending_deletions_rows/pending_deletion_rows/

> +                                             * current run until all inserts
> +                                             * and updates will be parsed. */

What happens if the row is deleted and then re-inserted within the same run?

This might be the concern I was referring to here:
  https://mail.openvswitch.org/pipermail/ovs-dev/2024-January/410541.html
Though I don't remember, it's been a hot minute.  Might be good to have a
test case for that.

Note: alternative solution to re-processign things as soon as a different
type of update is received is maybe to add a new CS event that signifies
a border between two separate updates and do re-processing on these events.
Not sure.  Some performance testing would be needed.


>      struct ovs_list deleted_untracked_rows; /* Stores rows deleted in the
>                                               * current run, that are not yet
>                                               * added to the track_list. */
> @@ -152,7 +155,8 @@ static bool ovsdb_idl_modify_row(struct ovsdb_idl_row *,
>                                   const struct shash *values, bool xor);
>  static void ovsdb_idl_parse_update(struct ovsdb_idl *,
>                                     const struct ovsdb_cs_update_event *);
> -static void ovsdb_idl_reparse_deleted(struct ovsdb_idl *);
> +static void ovsdb_idl_process_pending_deletions(struct ovsdb_idl *db);
> +static void ovsdb_idl_reparse_untracked_deletions(struct ovsdb_idl *);

These two functions are always called together, AFAICT.  It may be better
to morge the second one into the first.  The "process_pending_deletions"
name fits both operations.

>  static void ovsdb_idl_reparse_refs_to_inserted(struct ovsdb_idl *);
>  
>  static void ovsdb_idl_txn_process_reply(struct ovsdb_idl *,
> @@ -266,6 +270,8 @@ ovsdb_idl_create_unconnected(const struct ovsdb_idl_class 
> *class,
>          .txn = NULL,
>          .outstanding_txns = HMAP_INITIALIZER(&idl->outstanding_txns),
>          .verify_write_only = false,
> +        .pending_deletions_rows
> +            = OVS_LIST_INITIALIZER(&idl->pending_deletions_rows),
>          .deleted_untracked_rows
>              = OVS_LIST_INITIALIZER(&idl->deleted_untracked_rows),
>          .rows_to_reparse
> @@ -399,10 +405,14 @@ ovsdb_idl_set_leader_only(struct ovsdb_idl *idl, bool 
> leader_only)
>  static void
>  ovsdb_idl_clear(struct ovsdb_idl *db)
>  {
> -    /* Process deleted rows, removing them from the 'deleted_untracked_rows'
> -     * list and reparsing their backrefs.
> +    /* Process rows that have been marked for deletion. */
> +    ovsdb_idl_process_pending_deletions(db);
> +
> +    /* Process deleted rows that are not yet added to the track_list,
> +     * removing them from the 'deleted_untracked_rows' list and reparsing
> +     * their backrefs.
>       */
> -    ovsdb_idl_reparse_deleted(db);
> +    ovsdb_idl_reparse_untracked_deletions(db);
>  
>      /* Process backrefs of inserted rows, removing them from the
>       * 'rows_to_reparse' list.
> @@ -447,6 +457,7 @@ ovsdb_idl_clear(struct ovsdb_idl *db)
>  
>      /* Free rows deleted from tables with change tracking enabled. */
>      ovsdb_idl_track_clear__(db, true);
> +    ovs_assert(ovs_list_is_empty(&db->pending_deletions_rows));
>      ovs_assert(ovs_list_is_empty(&db->deleted_untracked_rows));
>      ovs_assert(ovs_list_is_empty(&db->rows_to_reparse));
>      db->change_seqno++;
> @@ -493,7 +504,8 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
>          ovsdb_cs_event_destroy(event);
>      }
>      ovsdb_idl_reparse_refs_to_inserted(idl);
> -    ovsdb_idl_reparse_deleted(idl);
> +    ovsdb_idl_process_pending_deletions(idl);
> +    ovsdb_idl_reparse_untracked_deletions(idl);
>      ovsdb_idl_row_destroy_postprocess(idl);
>  }
>  
> @@ -1588,14 +1600,33 @@ ovsdb_idl_parse_update(struct ovsdb_idl *idl,
>      }
>  }
>  
> -/* Reparses references to rows that have been deleted in the current IDL run.
> +/* Processes all rows that have been deleted in the current IDL run.
> + *
> + * This function must be called after all iserts and updates from the current

* inserts
But also, it's better to use the full word 'insertions'.  Here and in other 
places
in the patch.

> + * IDL run have been parsed i.e., after all calls to 
> ovsdb_idl_parse_update().
> + */
> +static void
> +ovsdb_idl_process_pending_deletions(struct ovsdb_idl *db)
> +{
> +    struct ovsdb_idl_row *row;
> +
> +    LIST_FOR_EACH_POP (row, pending_deletion_node,
> +                       &db->pending_deletions_rows) {
> +        ovs_list_init(&row->pending_deletion_node);
> +
> +        ovsdb_idl_delete_row(row);
> +    }
> +}
> +
> +/* Reparses references to rows that have been deleted in the current IDL run
> + * and that are not yet added to the track_list.
>   *
>   * To ensure that reference sources that are deleted are not reparsed,
> - * this function must be called after all updates have been processed in
> - * the current IDL run, i.e., after all calls to ovsdb_idl_parse_update().
> + * this function must be called after all deletions have been processed
> + * i.e., after all calls to ovsdb_idl_process_pending_deletions().
>   */
>  static void
> -ovsdb_idl_reparse_deleted(struct ovsdb_idl *db)
> +ovsdb_idl_reparse_untracked_deletions(struct ovsdb_idl *db)
>  {
>      struct ovsdb_idl_row *row;
>  
> @@ -1674,7 +1705,11 @@ ovsdb_idl_process_update(struct ovsdb_idl_table *table,
>      case OVSDB_CS_ROW_DELETE:
>          if (row && !ovsdb_idl_row_is_orphan(row)) {
>              /* XXX perhaps we should check the 'old' values? */
> -            ovsdb_idl_delete_row(row);
> +            /* Defer deletion processing until all updates of the
> +             * current IDL run.
> +             */

I'd combine the comment blocks and move the XXX one after the new one, with
a single empty line between them.

> +            ovs_list_push_back(&row->table->idl->pending_deletions_rows,
> +                               &row->pending_deletion_node);
>          } else {
>              VLOG_ERR_RL(&semantic_rl, "cannot delete missing row "UUID_FMT" "
>                          "from table %s",
> @@ -2359,6 +2394,7 @@ ovsdb_idl_row_create__(const struct 
> ovsdb_idl_table_class *class)
>      class->row_init(row);
>      ovs_list_init(&row->src_arcs);
>      ovs_list_init(&row->dst_arcs);
> +    ovs_list_init(&row->pending_deletion_node);
>      ovs_list_init(&row->reparse_node);
>      hmap_node_nullify(&row->txn_node);
>      ovs_list_init(&row->track_node);
> @@ -2489,10 +2525,6 @@ ovsdb_idl_insert_row(struct ovsdb_idl_row *row, const 
> struct shash *data)
>  static void
>  ovsdb_idl_delete_row(struct ovsdb_idl_row *row)
>  {
> -    /* If row has to be reparsed, reparse it before it's deleted. */
> -    if (!ovs_list_is_empty(&row->reparse_node)) {
> -        ovsdb_idl_row_parse(row);
> -    }
>      ovsdb_idl_remove_from_indexes(row);
>      ovsdb_idl_row_clear_arcs(row, true);
>      ovsdb_idl_row_destroy(row);
> diff --git a/tests/idltest.ovsschema b/tests/idltest.ovsschema
> index 65eadb961..4263076a1 100644
> --- a/tests/idltest.ovsschema
> +++ b/tests/idltest.ovsschema
> @@ -33,6 +33,15 @@
>              },
>              "min": 0
>            }
> +        },
> +        "l3": {
> +          "type": {
> +            "key": {
> +              "type": "uuid",
> +              "refTable": "link3"
> +            },
> +            "min": 0
> +          }
>          }
>        },
>        "isRoot" : true
> @@ -54,6 +63,23 @@
>        },
>        "isRoot" : true
>      },
> +    "link3": {
> +      "columns": {
> +        "i": {
> +          "type": "integer"
> +        },
> +        "l1": {
> +          "type": {
> +            "key": {
> +              "type": "uuid",
> +              "refTable": "link1"
> +            },
> +            "min": 0
> +          }
> +        }
> +      },
> +      "isRoot" : true
> +    },
>      "indexed": {
>        "columns": {
>          "i": {
> diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
> index 728d761d4..1a9075f17 100644
> --- a/tests/ovsdb-idl.at
> +++ b/tests/ovsdb-idl.at
> @@ -172,7 +172,7 @@ m4_define([OVSDB_CHECK_IDL_REGISTER_COLUMNS_PY],
>       [simple3:name,uset,uref],
>       [simple4:name],
>       [simple6:name,weak_ref],
> -     [link1:i,k,ka,l2],
> +     [link1:i,k,ka,l2,l3],
>       [link2:i,l1],
>       [indexed:i],
>       [singleton:name]))
> @@ -755,11 +755,11 @@ OVSDB_CHECK_IDL([simple idl, conditional, multiple 
> tables],
>  002: simple: change conditions
>  003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] 
> uuid=<1>
>  004: link1: change conditions
> -005: table link1: i=0 k=0 ka=[] l2= uuid=<2>
> +005: table link1: i=0 k=0 ka=[] l2= l3= uuid=<2>
>  005: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] 
> uuid=<1>
>  006: link2: change conditions
>  007: {"error":null,"result":[{"uuid":["uuid","<3>"]}]}
> -008: table link1: i=0 k=0 ka=[] l2= uuid=<2>
> +008: table link1: i=0 k=0 ka=[] l2= l3= uuid=<2>
>  008: table link2: i=3 l1= uuid=<3>
>  008: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] 
> uuid=<1>
>  009: done
> @@ -818,19 +818,19 @@ OVSDB_CHECK_IDL([self-linking idl, consistent ops],
>         "row": {"k": ["uuid", "#0#"]}}]']],
>    [[000: empty
>  001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]}
> -002: table link1: i=0 k=0 ka=[] l2= uuid=<0>
> +002: table link1: i=0 k=0 ka=[] l2= l3= uuid=<0>
>  003: 
> {"error":null,"result":[{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]}
> -004: table link1: i=0 k=0 ka=[] l2= uuid=<0>
> -004: table link1: i=1 k=2 ka=[] l2= uuid=<1>
> -004: table link1: i=2 k=1 ka=[] l2= uuid=<2>
> +004: table link1: i=0 k=0 ka=[] l2= l3= uuid=<0>
> +004: table link1: i=1 k=2 ka=[] l2= l3= uuid=<1>
> +004: table link1: i=2 k=1 ka=[] l2= l3= uuid=<2>
>  005: {"error":null,"result":[{"count":1}]}
> -006: table link1: i=0 k=0 ka=[] l2= uuid=<0>
> -006: table link1: i=1 k=1 ka=[] l2= uuid=<1>
> -006: table link1: i=2 k=1 ka=[] l2= uuid=<2>
> +006: table link1: i=0 k=0 ka=[] l2= l3= uuid=<0>
> +006: table link1: i=1 k=1 ka=[] l2= l3= uuid=<1>
> +006: table link1: i=2 k=1 ka=[] l2= l3= uuid=<2>
>  007: {"error":null,"result":[{"count":3}]}
> -008: table link1: i=0 k=0 ka=[] l2= uuid=<0>
> -008: table link1: i=1 k=0 ka=[] l2= uuid=<1>
> -008: table link1: i=2 k=0 ka=[] l2= uuid=<2>
> +008: table link1: i=0 k=0 ka=[] l2= l3= uuid=<0>
> +008: table link1: i=1 k=0 ka=[] l2= l3= uuid=<1>
> +008: table link1: i=2 k=0 ka=[] l2= l3= uuid=<2>
>  009: done
>  ]])
>  
> @@ -869,12 +869,12 @@ OVSDB_CHECK_IDL([self-linking idl, inconsistent ops],
>    [[000: empty
>  001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"details":"Table link1 
> column k row <0> references nonexistent row <1> in table 
> link1.","error":"referential integrity violation"}]}
>  002: 
> {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]}
> -003: table link1: i=1 k=1 ka=[] l2= uuid=<2>
> -003: table link1: i=2 k=1 ka=[] l2= uuid=<3>
> +003: table link1: i=1 k=1 ka=[] l2= l3= uuid=<2>
> +003: table link1: i=2 k=1 ka=[] l2= l3= uuid=<3>
>  004: {"error":null,"result":[{"count":2},{"details":"Table link1 column k 
> row <x> references nonexistent row <4> in table link1.","error":"referential 
> integrity violation"}]}
>  005: {"error":null,"result":[{"count":1},{"details":"cannot delete link1 row 
> <2> because of 1 remaining reference(s)","error":"referential integrity 
> violation"}]}
>  006: {"error":null,"result":[{"count":1}]}
> -007: table link1: i=1 k=1 ka=[] l2= uuid=<2>
> +007: table link1: i=1 k=1 ka=[] l2= l3= uuid=<2>
>  008: {"error":null,"result":[{"count":1}]}
>  009: empty
>  010: done
> @@ -917,15 +917,15 @@ OVSDB_CHECK_IDL([self-linking idl, sets],
>         "where": []}]']],
>    [[000: empty
>  001: 
> {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]}
> -002: table link1: i=0 k=0 ka=[0] l2= uuid=<0>
> -002: table link1: i=1 k=0 ka=[1] l2= uuid=<1>
> -002: table link1: i=2 k=0 ka=[2] l2= uuid=<2>
> -002: table link1: i=3 k=0 ka=[3] l2= uuid=<3>
> +002: table link1: i=0 k=0 ka=[0] l2= l3= uuid=<0>
> +002: table link1: i=1 k=0 ka=[1] l2= l3= uuid=<1>
> +002: table link1: i=2 k=0 ka=[2] l2= l3= uuid=<2>
> +002: table link1: i=3 k=0 ka=[3] l2= l3= uuid=<3>
>  003: {"error":null,"result":[{"count":4}]}
> -004: table link1: i=0 k=0 ka=[0 1 2 3] l2= uuid=<0>
> -004: table link1: i=1 k=0 ka=[0 1 2 3] l2= uuid=<1>
> -004: table link1: i=2 k=0 ka=[0 1 2 3] l2= uuid=<2>
> -004: table link1: i=3 k=0 ka=[0 1 2 3] l2= uuid=<3>
> +004: table link1: i=0 k=0 ka=[0 1 2 3] l2= l3= uuid=<0>
> +004: table link1: i=1 k=0 ka=[0 1 2 3] l2= l3= uuid=<1>
> +004: table link1: i=2 k=0 ka=[0 1 2 3] l2= l3= uuid=<2>
> +004: table link1: i=3 k=0 ka=[0 1 2 3] l2= l3= uuid=<3>
>  005: {"error":null,"result":[{"count":1},{"details":"Table link1 column ka 
> row <2> references nonexistent row <4> in table link1.","error":"referential 
> integrity violation"}]}
>  006: {"error":null,"result":[{"count":4}]}
>  007: empty
> @@ -945,7 +945,7 @@ OVSDB_CHECK_IDL([external-linking idl, consistent ops],
>         "uuid-name": "row1"}]']],
>    [[000: empty
>  001: 
> {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
> -002: table link1: i=1 k=1 ka=[] l2=0 uuid=<1>
> +002: table link1: i=1 k=1 ka=[] l2=0 l3= uuid=<1>
>  002: table link2: i=0 l1= uuid=<0>
>  003: done
>  ]])
> @@ -1010,8 +1010,8 @@ OVSDB_CHECK_IDL_PY([external-linking idl, insert ops],
>    [['linktest']],
>    [[000: empty
>  001: commit, status=success
> -002: table link1: i=1 k=1 ka=[1] l2= uuid=<0>
> -002: table link1: i=2 k=1 ka=[1 2] l2= uuid=<1>
> +002: table link1: i=1 k=1 ka=[1] l2= l3= uuid=<0>
> +002: table link1: i=2 k=1 ka=[1 2] l2= l3= uuid=<1>
>  003: done
>  ]])
>  
> @@ -1020,7 +1020,7 @@ OVSDB_CHECK_IDL_PY([getattr idl, insert ops],
>    [['getattrtest']],
>    [[000: empty
>  001: commit, status=success
> -002: table link1: i=2 k=2 ka=[] l2= uuid=<0>
> +002: table link1: i=2 k=2 ka=[] l2= l3= uuid=<0>
>  003: done
>  ]])
>  
> @@ -1077,19 +1077,19 @@ AT_CHECK([test-ovsdb 
> '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 idl uni
>  AT_CHECK([sort stdout | uuidfilt], [0],
>      [[000: empty
>  001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]}
> -002: table link1: i=0 k=0 ka=[] l2= uuid=<0>
> +002: table link1: i=0 k=0 ka=[] l2= l3= uuid=<0>
>  003: 
> {"error":null,"result":[{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]}
> -004: table link1: i=0 k=0 ka=[] l2= uuid=<0>
> -004: table link1: i=1 k=2 ka=[] l2= uuid=<1>
> -004: table link1: i=2 k=1 ka=[] l2= uuid=<2>
> +004: table link1: i=0 k=0 ka=[] l2= l3= uuid=<0>
> +004: table link1: i=1 k=2 ka=[] l2= l3= uuid=<1>
> +004: table link1: i=2 k=1 ka=[] l2= l3= uuid=<2>
>  005: {"error":null,"result":[{"count":1}]}
> -006: table link1: i=0 k=0 ka=[] l2= uuid=<0>
> -006: table link1: i=1 k=1 ka=[] l2= uuid=<1>
> -006: table link1: i=2 k=1 ka=[] l2= uuid=<2>
> +006: table link1: i=0 k=0 ka=[] l2= l3= uuid=<0>
> +006: table link1: i=1 k=1 ka=[] l2= l3= uuid=<1>
> +006: table link1: i=2 k=1 ka=[] l2= l3= uuid=<2>
>  007: {"error":null,"result":[{"count":3}]}
> -008: table link1: i=0 k=0 ka=[] l2= uuid=<0>
> -008: table link1: i=1 k=0 ka=[] l2= uuid=<1>
> -008: table link1: i=2 k=0 ka=[] l2= uuid=<2>
> +008: table link1: i=0 k=0 ka=[] l2= l3= uuid=<0>
> +008: table link1: i=1 k=0 ka=[] l2= l3= uuid=<1>
> +008: table link1: i=2 k=0 ka=[] l2= l3= uuid=<2>
>  009: done
>  ]])
>  
> @@ -1097,10 +1097,12 @@ AT_CHECK([sort stdout | uuidfilt], [0],
>  AT_CHECK([grep ovsdb_idl stderr | sort], [0], [dnl
>  test-ovsdb|ovsdb_idl|idltest database lacks indexed table (database needs 
> upgrade?)
>  test-ovsdb|ovsdb_idl|idltest database lacks link2 table (database needs 
> upgrade?)
> +test-ovsdb|ovsdb_idl|idltest database lacks link3 table (database needs 
> upgrade?)
>  test-ovsdb|ovsdb_idl|idltest database lacks simple5 table (database needs 
> upgrade?)
>  test-ovsdb|ovsdb_idl|idltest database lacks simple6 table (database needs 
> upgrade?)
>  test-ovsdb|ovsdb_idl|idltest database lacks singleton table (database needs 
> upgrade?)
>  test-ovsdb|ovsdb_idl|link1 table in idltest database lacks l2 column 
> (database needs upgrade?)
> +test-ovsdb|ovsdb_idl|link1 table in idltest database lacks l3 column 
> (database needs upgrade?)
>  test-ovsdb|ovsdb_idl|simple7 table in idltest database lacks id column 
> (database needs upgrade?)
>  ])
>  
> @@ -1780,7 +1782,7 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially 
> empty, strong references, in
>  001: 
> {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
>  002: {"error":null,"result":[{"count":1}]}
>  003: sleep
> -004: table link1: inserted row: i=1 k=1 ka=[] l2= uuid=<0>
> +004: table link1: inserted row: i=1 k=1 ka=[] l2= l3= uuid=<0>
>  004: table link1: updated columns: i k
>  005: done
>  ]])
> @@ -2015,7 +2017,7 @@ OVSDB_CHECK_IDL_NOTIFY([simple link idl verify notify],
>  001: 
> {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
>  002: event:create, row={i=1 l2=[<1>]}, uuid=<0>, updates=None
>  002: event:create, row={i=2 l1=[<0>]}, uuid=<1>, updates=None
> -002: table link1: i=1 k=1 ka=[] l2=2 uuid=<0>
> +002: table link1: i=1 k=1 ka=[] l2=2 l3= uuid=<0>
>  002: table link2: i=2 l1=1 uuid=<1>
>  003: done
>  ]])
> @@ -2762,14 +2764,14 @@ OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs 
> to link1],
>  001: 
> {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]}
>  002: {"error":null,"result":[{"count":1}]}
>  003: sleep
> -004: table link1: inserted row: i=1 k=1 ka=[] l2= uuid=<1>
> +004: table link1: inserted row: i=1 k=1 ka=[] l2= l3= uuid=<1>
>  004: table link1: updated columns: i k
>  004: table link2: inserted row: i=1 l1=1 uuid=<0>
>  004: table link2: inserted/deleted row: i=2 l1=1 uuid=<2>
>  004: table link2: updated columns: i l1
>  004: table link2: updated columns: i l1
>  005: {"error":null,"result":[{"count":1}]}
> -006: table link1: i=1 k=1 ka=[] l2= uuid=<1>
> +006: table link1: i=1 k=1 ka=[] l2= l3= uuid=<1>
>  007: done
>  ]])
>  OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs to link2],
> @@ -2807,8 +2809,8 @@ OVSDB_CHECK_IDL_TRACK([track, insert and delete, refs 
> to link2],
>  001: 
> {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]}
>  002: {"error":null,"result":[{"count":1}]}
>  003: sleep
> -004: table link1: inserted row: i=1 k=1 ka=[] l2=1 uuid=<0>
> -004: table link1: inserted/deleted row: i=2 k=1 ka=[] l2=1 uuid=<2>
> +004: table link1: inserted row: i=1 k=1 ka=[] l2=1 l3= uuid=<0>
> +004: table link1: inserted/deleted row: i=2 k=1 ka=[] l2=1 l3= uuid=<2>
>  004: table link1: updated columns: i k l2
>  004: table link1: updated columns: i k l2
>  004: table link2: inserted row: i=1 l1= uuid=<1>
> @@ -3057,3 +3059,77 @@ AT_CHECK([grep -qE "assertion !.*txn->assert_read_only 
> failed" stderr])
>  
>  OVSDB_SERVER_SHUTDOWN
>  AT_CLEANUP
> +
> +dnl This test checks the order of insert and delete operations, ensuring that
> +dnl dependent rows (e.g., `link3` before `link1`) are processed correctly.
> +dnl It's assumed that in the first update, link1 is processed before link3,
> +dnl and in the second update, link3 is deleted before link1. We expect to see
> +dnl a valid link to link3 after link1 is deleted.

May need to add a note that this depends on the order of hashes and so on the
compiler flags and the CPU architecture.

Best regards, Ilya Maximets.
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to