From 23d2611b2436695524d6b270f2189e3db471d246 Mon Sep 17 00:00:00 2001 From: Ed Warnicke Date: Mon, 11 May 2015 11:56:09 -0700 Subject: [PATCH] Fix race condition in initial connection. We must register the OvsdbConnectionCreateCommand prior to registerCallback or we will get race conditions. *Before* any bridge information can be successfully written to the operational datastore, the OvsdbNode *must* be written. The txInvoker guarantees writes occur in the order they were provided to *it*. If we have: txInvoker.invoke(new OvsdbNodeCreateCommand(key, null,null)); registerCallBack(); We can guarantee that, and thus guarantee we will not have race conditions. However, if we reverse that: registerCallBack(); txInvoker.invoke(new OvsdbNodeCreateCommand(key, null,null)); We are guarenteed to have race conditions, as the results of the original monitor dump get written to the datastore before the OvsdbNode gets written. Please note: ovsdb is actively broken out of the box due to this race conditions, so this must be corrected ASAP. Change-Id: Id71221f7665ece5ec4b2eb9a0b39465618bada01 Signed-off-by: Ed Warnicke --- .../southbound/OvsdbConnectionInstance.java | 39 +++++++++++-------- .../southbound/OvsdbConnectionManager.java | 3 +- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionInstance.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionInstance.java index 4c5548879..757ebd024 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionInstance.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionInstance.java @@ -35,6 +35,7 @@ import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable; import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactCommand; import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactInvoker; import org.opendaylight.ovsdb.southbound.ovsdb.transact.TransactInvokerImpl; +import org.opendaylight.ovsdb.southbound.transactions.md.OvsdbNodeCreateCommand; import org.opendaylight.ovsdb.southbound.transactions.md.TransactionInvoker; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo; import org.slf4j.Logger; @@ -50,12 +51,13 @@ public class OvsdbConnectionInstance implements OvsdbClient { private TransactionInvoker txInvoker; private Map transactInvokers = new HashMap(); private MonitorCallBack callback; + private ConnectionInfo key; OvsdbConnectionInstance(ConnectionInfo key,OvsdbClient client,TransactionInvoker txInvoker) { this.connectionInfo = key; this.client = client; this.txInvoker = txInvoker; - registerCallBack(); + this.key = key; } public void transact(TransactCommand command) { @@ -64,25 +66,28 @@ public class OvsdbConnectionInstance implements OvsdbClient { } } - private void registerCallBack() { - this.callback = new OvsdbMonitorCallback(connectionInfo,txInvoker); - try { - List databases = getDatabases().get(); - if (databases != null) { - for (String database : databases) { - DatabaseSchema dbSchema = getSchema(database).get(); - if (dbSchema != null) { - transactInvokers.put(dbSchema, new TransactInvokerImpl(this,dbSchema)); - monitorAllTables(database, dbSchema); - } else { - LOG.warn("No schema reported for database {} for key {}",database,connectionInfo); + public void init() { + if ( this.callback == null) { + txInvoker.invoke(new OvsdbNodeCreateCommand(key, null,null)); + this.callback = new OvsdbMonitorCallback(connectionInfo,txInvoker); + try { + List databases = getDatabases().get(); + if (databases != null) { + for (String database : databases) { + DatabaseSchema dbSchema = getSchema(database).get(); + if (dbSchema != null) { + transactInvokers.put(dbSchema, new TransactInvokerImpl(this,dbSchema)); + monitorAllTables(database, dbSchema); + } else { + LOG.warn("No schema reported for database {} for key {}",database,connectionInfo); + } } + } else { + LOG.warn("No databases reported from {}",connectionInfo); } - } else { - LOG.warn("No databases reported from {}",connectionInfo); + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Exception attempting to initialize {}: {}",connectionInfo,e); } - } catch (InterruptedException | ExecutionException e) { - LOG.warn("Exception attempting to initialize {}: {}",connectionInfo,e); } } diff --git a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java index dbb523627..fc8361f72 100644 --- a/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java +++ b/southbound/southbound-impl/src/main/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManager.java @@ -19,7 +19,6 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.ovsdb.lib.OvsdbClient; import org.opendaylight.ovsdb.lib.OvsdbConnectionListener; import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService; -import org.opendaylight.ovsdb.southbound.transactions.md.OvsdbNodeCreateCommand; import org.opendaylight.ovsdb.southbound.transactions.md.OvsdbNodeRemoveCommand; import org.opendaylight.ovsdb.southbound.transactions.md.TransactionInvoker; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAttributes; @@ -55,7 +54,7 @@ public class OvsdbConnectionManager implements OvsdbConnectionListener, AutoClos ConnectionInfo key = SouthboundMapper.createConnectionInfo(externalClient); OvsdbConnectionInstance client = new OvsdbConnectionInstance(key,externalClient,txInvoker); putConnectionInstance(key, client); - txInvoker.invoke(new OvsdbNodeCreateCommand(key, null,null)); + client.init(); } @Override -- 2.36.6