Fix unsynchronized access to TransactionChain 42/15242/1
authorRobert Varga <rovarga@cisco.com>
Tue, 20 Jan 2015 12:08:54 +0000 (13:08 +0100)
committerDana Kutenicsova <dkutenic@cisco.com>
Fri, 13 Feb 2015 08:24:56 +0000 (09:24 +0100)
The background resynchronization task instantiated transactions without
holding RIBImpl lock, leading to:

Exception in thread "Thread-29" java.lang.IllegalStateException: Previous transaction DOM-OPER-1298 is not ready yet
        at com.google.common.base.Preconditions.checkState(Preconditions.java:176)
        at org.opendaylight.controller.md.sal.dom.store.impl.DOMStoreTransactionChainImpl$Allocated.getSnapshot(DOMStoreTransactionChainImpl.java:68)
        at org.opendaylight.controller.md.sal.dom.store.impl.DOMStoreTransactionChainImpl.getSnapshot(DOMStoreTransactionChainImpl.java:111)
        at org.opendaylight.controller.md.sal.dom.store.impl.DOMStoreTransactionChainImpl.newReadWriteTransaction(DOMStoreTransactionChainImpl.java:131)
        at org.opendaylight.controller.md.sal.dom.broker.impl.AbstractDOMForwardedTransactionFactory.newReadWriteTransaction(AbstractDOMForwardedTransactionFactory.java:206)
        at org.opendaylight.controller.md.sal.dom.broker.impl.PingPongTransactionChain.slowAllocateTransaction(PingPongTransactionChain.java:127)
        at org.opendaylight.controller.md.sal.dom.broker.impl.PingPongTransactionChain.allocateTransaction(PingPongTransactionChain.java:144)
        at org.opendaylight.controller.md.sal.dom.broker.impl.PingPongTransactionChain.newReadWriteTransaction(PingPongTransactionChain.java:295)
        at org.opendaylight.controller.md.sal.dom.broker.impl.PingPongTransactionChain.newWriteOnlyTransaction(PingPongTransactionChain.java:326)
        at org.opendaylight.controller.md.sal.binding.impl.BindingTranslatedTransactionChain.newWriteOnlyTransaction(BindingTranslatedTransactionChain.java:77)
        at org.opendaylight.protocol.bgp.rib.impl.RIBImpl$1.run(RIBImpl.java:125)
        at java.lang.Thread.run(Thread.java:745)

Change-Id: I8b5b34f313dbd1b2584ea73aef37fb6e5c6b5120
Signed-off-by: Robert Varga <rovarga@cisco.com>
(cherry picked from commit 4fa6575c890501ef7e6016e65add3dc80d353f57)

bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java

index a46e3cb284cca07f608a1696f365bad39ec195be..c757e34dd1a04bf9ca7844635463080d58ed596c 100644 (file)
@@ -99,20 +99,21 @@ public final class RIBImpl extends DefaultRibReference implements AutoCloseable,
                 final Peer peer = RIBImpl.this.peers.take();
                 LOG.debug("Advertizing loc-rib to new peer {}.", peer);
                 for (final BgpTableType key : RIBImpl.this.localTables) {
-                    final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(RIBImpl.this.ribOuts, RIBImpl.this.comparator, RIBImpl.this.chain.newWriteOnlyTransaction());
-                    final AbstractAdjRIBs<?, ?, ?> adj = (AbstractAdjRIBs<?, ?, ?>) RIBImpl.this.tables.get(new TablesKey(key.getAfi(), key.getSafi()));
-                    adj.addAllEntries(trans);
-                    Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
-                        @Override
-                        public void onSuccess(final Void result) {
-                            LOG.trace("Advertizing {} to peer {} committed successfully", key.getAfi(), peer);
-                        }
-
-                        @Override
-                        public void onFailure(final Throwable t) {
-                            LOG.error("Failed to update peer {} with RIB {}", peer, t);
-                        }
-                    });
+                    synchronized (RIBImpl.this) {
+                        final AdjRIBsTransactionImpl trans = new AdjRIBsTransactionImpl(RIBImpl.this.ribOuts, RIBImpl.this.comparator, RIBImpl.this.chain.newWriteOnlyTransaction());
+                        final AbstractAdjRIBs<?, ?, ?> adj = (AbstractAdjRIBs<?, ?, ?>) RIBImpl.this.tables.get(new TablesKey(key.getAfi(), key.getSafi()));
+                        adj.addAllEntries(trans);
+                        Futures.addCallback(trans.commit(), new FutureCallback<Void>() {
+                            @Override
+                            public void onSuccess(final Void result) {
+                                LOG.trace("Advertizing {} to peer {} committed successfully", key.getAfi(), peer);
+                            }
+                            @Override
+                            public void onFailure(final Throwable t) {
+                                LOG.error("Failed to update peer {} with RIB {}", peer, t);
+                            }
+                        });
+                    }
                 }
             } catch (final InterruptedException e) {