On 7/21/23 15:10, Ilya Maximets wrote:
> 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.

I believe, there is a similar issue on relay server when receiving
an update2 message that violates the type size.  It's not related
to the file-column-diff, but the mechanics of the issue is the same.
Relay should re-connect and eventually recover though, once the
transaction history is exhausted, but it's not good.  I'll work on a
fix for that as well.

> 
> 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