@@ -75,7 +75,7 @@ static struct shash all_commands = SHASH_INITIALIZER(&all_commands);
75
75
static char * get_table (const char * , const struct ovsdb_idl_table_class * * );
76
76
static char * set_column (const struct ovsdb_idl_table_class * ,
77
77
const struct ovsdb_idl_row * , const char * ,
78
- struct ovsdb_symbol_table * );
78
+ struct ovsdb_symbol_table * , bool use_partial_update );
79
79
80
80
81
81
static struct option *
@@ -1325,11 +1325,17 @@ cmd_find(struct ctl_context *ctx)
1325
1325
}
1326
1326
1327
1327
/* Sets the column of 'row' in 'table'. Returns NULL on success or a
1328
- * malloc()'ed error message on failure. */
1328
+ * malloc()'ed error message on failure.
1329
+ *
1330
+ * If 'use_partial_update' is true, then this function will try to use
1331
+ * partial set/map updates, if possible. As a side effect, result will
1332
+ * not be reflected in the IDL until the transaction is committed.
1333
+ * The last access to a particular column is a good candidate to use
1334
+ * this option. */
1329
1335
static char * OVS_WARN_UNUSED_RESULT
1330
1336
set_column (const struct ovsdb_idl_table_class * table ,
1331
1337
const struct ovsdb_idl_row * row , const char * arg ,
1332
- struct ovsdb_symbol_table * symtab )
1338
+ struct ovsdb_symbol_table * symtab , bool use_partial_update )
1333
1339
{
1334
1340
const struct ovsdb_idl_column * column ;
1335
1341
char * key_string = NULL ;
@@ -1352,7 +1358,7 @@ set_column(const struct ovsdb_idl_table_class *table,
1352
1358
1353
1359
if (key_string ) {
1354
1360
union ovsdb_atom key , value ;
1355
- struct ovsdb_datum datum ;
1361
+ struct ovsdb_datum * datum ;
1356
1362
1357
1363
if (column -> type .value .type == OVSDB_TYPE_VOID ) {
1358
1364
error = xasprintf ("cannot specify key to set for non-map column "
@@ -1371,16 +1377,22 @@ set_column(const struct ovsdb_idl_table_class *table,
1371
1377
goto out ;
1372
1378
}
1373
1379
1374
- ovsdb_datum_init_empty (& datum );
1375
- ovsdb_datum_add_unsafe (& datum , & key , & value , & column -> type , NULL );
1380
+ datum = xmalloc (sizeof * datum );
1381
+ ovsdb_datum_init_empty (datum );
1382
+ ovsdb_datum_add_unsafe (datum , & key , & value , & column -> type , NULL );
1376
1383
1377
1384
ovsdb_atom_destroy (& key , column -> type .key .type );
1378
1385
ovsdb_atom_destroy (& value , column -> type .value .type );
1379
1386
1380
- ovsdb_datum_union (& datum , ovsdb_idl_read (row , column ),
1381
- & column -> type );
1382
- ovsdb_idl_txn_verify (row , column );
1383
- ovsdb_idl_txn_write (row , column , & datum );
1387
+ if (use_partial_update ) {
1388
+ ovsdb_idl_txn_write_partial_map (row , column , datum );
1389
+ } else {
1390
+ ovsdb_datum_union (datum , ovsdb_idl_read (row , column ),
1391
+ & column -> type );
1392
+ ovsdb_idl_txn_verify (row , column );
1393
+ ovsdb_idl_txn_write (row , column , datum );
1394
+ free (datum );
1395
+ }
1384
1396
} else {
1385
1397
struct ovsdb_datum datum ;
1386
1398
@@ -1441,7 +1453,8 @@ cmd_set(struct ctl_context *ctx)
1441
1453
}
1442
1454
1443
1455
for (i = 3 ; i < ctx -> argc ; i ++ ) {
1444
- ctx -> error = set_column (table , row , ctx -> argv [i ], ctx -> symtab );
1456
+ ctx -> error = set_column (table , row , ctx -> argv [i ], ctx -> symtab ,
1457
+ ctx -> last_command );
1445
1458
if (ctx -> error ) {
1446
1459
return ;
1447
1460
}
@@ -1479,7 +1492,7 @@ cmd_add(struct ctl_context *ctx)
1479
1492
const struct ovsdb_idl_column * column ;
1480
1493
const struct ovsdb_idl_row * row ;
1481
1494
const struct ovsdb_type * type ;
1482
- struct ovsdb_datum old ;
1495
+ struct ovsdb_datum new ;
1483
1496
int i ;
1484
1497
1485
1498
ctx -> error = get_table (table_name , & table );
@@ -1503,7 +1516,13 @@ cmd_add(struct ctl_context *ctx)
1503
1516
}
1504
1517
1505
1518
type = & column -> type ;
1506
- ovsdb_datum_clone (& old , ovsdb_idl_read (row , column ));
1519
+
1520
+ if (ctx -> last_command ) {
1521
+ ovsdb_datum_init_empty (& new );
1522
+ } else {
1523
+ ovsdb_datum_clone (& new , ovsdb_idl_read (row , column ));
1524
+ }
1525
+
1507
1526
for (i = 4 ; i < ctx -> argc ; i ++ ) {
1508
1527
struct ovsdb_type add_type ;
1509
1528
struct ovsdb_datum add ;
@@ -1514,23 +1533,41 @@ cmd_add(struct ctl_context *ctx)
1514
1533
ctx -> error = ovsdb_datum_from_string (& add , & add_type , ctx -> argv [i ],
1515
1534
ctx -> symtab );
1516
1535
if (ctx -> error ) {
1517
- ovsdb_datum_destroy (& old , & column -> type );
1536
+ ovsdb_datum_destroy (& new , & column -> type );
1518
1537
return ;
1519
1538
}
1520
- ovsdb_datum_union (& old , & add , type );
1539
+ ovsdb_datum_union (& new , & add , type );
1521
1540
ovsdb_datum_destroy (& add , type );
1522
1541
}
1523
- if (old .n > type -> n_max ) {
1542
+
1543
+ if (!ctx -> last_command && new .n > type -> n_max ) {
1524
1544
ctl_error (ctx , "\"add\" operation would put %u %s in column %s of "
1525
1545
"table %s but the maximum number is %u" ,
1526
- old .n ,
1546
+ new .n ,
1527
1547
type -> value .type == OVSDB_TYPE_VOID ? "values" : "pairs" ,
1528
1548
column -> name , table -> name , type -> n_max );
1529
- ovsdb_datum_destroy (& old , & column -> type );
1549
+ ovsdb_datum_destroy (& new , & column -> type );
1530
1550
return ;
1531
1551
}
1532
- ovsdb_idl_txn_verify (row , column );
1533
- ovsdb_idl_txn_write (row , column , & old );
1552
+
1553
+ if (ctx -> last_command ) {
1554
+ /* Partial updates can only be made one by one. */
1555
+ for (i = 0 ; i < new .n ; i ++ ) {
1556
+ struct ovsdb_datum * datum = xmalloc (sizeof * datum );
1557
+
1558
+ ovsdb_datum_init_empty (datum );
1559
+ ovsdb_datum_add_from_index_unsafe (datum , & new , i , type );
1560
+ if (ovsdb_type_is_map (type )) {
1561
+ ovsdb_idl_txn_write_partial_map (row , column , datum );
1562
+ } else {
1563
+ ovsdb_idl_txn_write_partial_set (row , column , datum );
1564
+ }
1565
+ }
1566
+ ovsdb_datum_destroy (& new , & column -> type );
1567
+ } else {
1568
+ ovsdb_idl_txn_verify (row , column );
1569
+ ovsdb_idl_txn_write (row , column , & new );
1570
+ }
1534
1571
1535
1572
invalidate_cache (ctx );
1536
1573
}
@@ -1769,7 +1806,7 @@ cmd_create(struct ctl_context *ctx)
1769
1806
}
1770
1807
1771
1808
for (i = 2 ; i < ctx -> argc ; i ++ ) {
1772
- ctx -> error = set_column (table , row , ctx -> argv [i ], ctx -> symtab );
1809
+ ctx -> error = set_column (table , row , ctx -> argv [i ], ctx -> symtab , false );
1773
1810
if (ctx -> error ) {
1774
1811
return ;
1775
1812
}
@@ -2620,7 +2657,8 @@ ctl_list_db_tables_usage(void)
2620
2657
/* Initializes 'ctx' from 'command'. */
2621
2658
void
2622
2659
ctl_context_init_command (struct ctl_context * ctx ,
2623
- struct ctl_command * command )
2660
+ struct ctl_command * command ,
2661
+ bool last )
2624
2662
{
2625
2663
ctx -> argc = command -> argc ;
2626
2664
ctx -> argv = command -> argv ;
@@ -2629,6 +2667,7 @@ ctl_context_init_command(struct ctl_context *ctx,
2629
2667
ds_swap (& ctx -> output , & command -> output );
2630
2668
ctx -> table = command -> table ;
2631
2669
ctx -> try_again = false;
2670
+ ctx -> last_command = last ;
2632
2671
ctx -> error = NULL ;
2633
2672
}
2634
2673
@@ -2640,7 +2679,7 @@ ctl_context_init(struct ctl_context *ctx, struct ctl_command *command,
2640
2679
void (* invalidate_cache_cb )(struct ctl_context * ))
2641
2680
{
2642
2681
if (command ) {
2643
- ctl_context_init_command (ctx , command );
2682
+ ctl_context_init_command (ctx , command , false );
2644
2683
}
2645
2684
ctx -> idl = idl ;
2646
2685
ctx -> txn = txn ;
@@ -2684,7 +2723,7 @@ ctl_set_column(const char *table_name, const struct ovsdb_idl_row *row,
2684
2723
if (error ) {
2685
2724
return error ;
2686
2725
}
2687
- error = set_column (table , row , arg , symtab );
2726
+ error = set_column (table , row , arg , symtab , false );
2688
2727
if (error ) {
2689
2728
return error ;
2690
2729
}
0 commit comments