On 7/21/23 14:44, Peng He wrote:
> Hi, Ilya,
> 
> Suppose you have a column which is a set with limited integers (suppose min: 
> 0, max: 2), the following operation will generate a record in db file with 3 
> integers:
> 
> first, set column A to [0],
> then, set column A to [1,2],
> 
> after that the column A is recorded as [0,1,2], as [0] diff [1,2] == [0, 1, 
> 2].

Hmm, good catch!

The file is correct.  However, the ovsdb-server is too strict while reading
these records.  Could you try the following change:

diff --git a/ovsdb/file.c b/ovsdb/file.c
index 400b34794..6e7e47ca6 100644
--- a/ovsdb/file.c
+++ b/ovsdb/file.c
@@ -107,7 +107,14 @@ ovsdb_file_update_row_from_json(struct ovsdb_row *row, 
bool converting,
                                       column_name, schema->name);
         }
 
-        error = ovsdb_datum_from_json(&datum, &column->type, node->data, NULL);
+        if (row_contains_diff) {
+            /* Diff may violate the type size rules. */
+            error = ovsdb_transient_datum_from_json(&datum, &column->type,
+                                                    node->data);
+        } else {
+            error = ovsdb_datum_from_json(&datum, &column->type,
+                                          node->data, NULL);
+        }
         if (error) {
             return error;
         }
---

?

The type constraints will be evaluated later while applying the diff
to the existing row.

Best regards, Ilya Maximets.

> Such a bug can be reproduced by a test suite below:
> 
> 
> AT_SETUP([ovsdb-server diff columns])
> on_exit 'kill `cat *.pid`'
> AT_DATA([schema],
>   [[{"name": "mydb",
>      "tables": {
>        "Root": {
>          "columns": {
>            "managers": {
>              "type": {
>                "key": {"type": "uuid", "refTable": "Manager"},
>                "min": 0,
>                "max": "unlimited"}}}},
>        "Manager": {
>          "columns": {
>            "target": {
>              "type": "string"},
>            "read_only": {
>              "type": {
>                "key": "boolean",
>                "min": 0,
>                "max": 1}},
>            "is_connected": {
>              "type": {
>                "key": "boolean",
>                "min": 0,
>                "max": 1}}}},
>        "ordinals": {
>          "columns": {
>            "number": {"type": {
>                       "key": {"type" : "integer"},
>                       "min": 0,
>                       "max": 2}},
>            "name": {"type": "string"}},
>          "indexes": [["name"]]}
>     },
>      "version": "5.1.3",
>      "cksum": "12345678 9"
> }
> ]])
> AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore])
> AT_CHECK(
>   [[ovsdb-tool transact db \
>      '["mydb",
>        {"op": "insert",
>         "table": "Root",
>         "row": {
>           "managers": ["set", [["named-uuid", "x"]]]}},
>        {"op": "insert",
>         "table": "Manager",
>         "uuid-name": "x",
>         "row": {"target": "ptcp:0:127.0.0.1",
>                "read_only": false}}]']], [0], [ignore], [ignore])
> 
> AT_CHECK([ovsdb-server --detach --no-chdir --log-file --pidfile 
> --remote=db:mydb,Root,managers db], [0], [ignore], [ignore])
> PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
> AT_CHECK([ovsdb-client get-schema-version tcp:127.0.0.1:$TCP_PORT mydb], [0], 
> [5.1.3
> ])
> 
> AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT \
>         ['["mydb",
>          {"op": "insert",
>           "table": "ordinals",
>           "row": {"name": "two", "number": 0}}
>          ]']], [0], [stdout], [ignore])
> 
> AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT \
>         ['["mydb",
>          {"op": "update",
>           "table": "ordinals",
>           "where": [["name", "==", "two"]],
>           "row": {"number": ["set", [1,2]]}}
>          ]']], [0], [stdout], [ignore])
> 
> AT_CHECK([ovs-appctl -t ovsdb-server exit])
> AT_CHECK([ovsdb-server --detach --no-chdir --log-file --pidfile 
> --remote=db:mydb,Root,managers db], [0], [ignore], [ignore])
> 
> OVSDB_SERVER_SHUTDOWN(["
>   /No status column present in the Manager table/d
> "])
> AT_CLEANUP
> 
> when reboot ovsdb-server, it will warn in the log:
> 2023-07-21T12:43:55Z|00001|vlog|INFO|opened log file 
> /root/ovs/tests/testsuite.dir/2044/ovsdb-server.log
> 2023-07-21T12:43:55Z|00002|ovsdb_server|ERR|syntax "["set",[0,1,2]]": syntax 
> error: set must have 0 to 2 members but 3 are present
> 
> 
> -- 
> hepeng

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

Reply via email to