Bug-7614: LocRibWriter does not recover well from transaction chain failure
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / LocRibWriter.java
index 3cbd173c11b78eaa91231ea076e590824f3bb973..9225c5254225e13a61e021e5d81f7849f6c72367 100644 (file)
@@ -65,13 +65,16 @@ final class LocRibWriter implements AutoCloseable, ClusteredDOMDataTreeChangeLis
 
     private final Map<PathArgument, RouteEntry> routeEntries = new HashMap<>();
     private final YangInstanceIdentifier locRibTarget;
-    private final DOMTransactionChain chain;
+    private final NodeIdentifierWithPredicates tableKey;
+    private DOMTransactionChain chain;
     private final ExportPolicyPeerTracker exportPolicyPeerTracker;
     private final NodeIdentifier attributesIdentifier;
     private final Long ourAs;
     private final RIBSupport ribSupport;
     private final TablesKey localTablesKey;
-    private final ListenerRegistration<LocRibWriter> reg;
+    private final YangInstanceIdentifier target;
+    private final DOMDataTreeChangeService service;
+    private ListenerRegistration<LocRibWriter> reg;
     private final PathSelectionMode pathSelectionMode;
     private final UnsignedInt32Counter routeCounter;
 
@@ -79,24 +82,33 @@ final class LocRibWriter implements AutoCloseable, ClusteredDOMDataTreeChangeLis
         final Long ourAs, final DOMDataTreeChangeService service, final ExportPolicyPeerTracker exportPolicyPeerTracker, final TablesKey tablesKey,
         @Nonnull final PathSelectionMode pathSelectionMode, final UnsignedInt32Counter routeCounter) {
         this.chain = Preconditions.checkNotNull(chain);
+        this.target = Preconditions.checkNotNull(target);
         final NodeIdentifierWithPredicates tableKey = RibSupportUtils.toYangTablesKey(tablesKey);
         this.localTablesKey = tablesKey;
+        this.tableKey = tableKey;
         this.locRibTarget = YangInstanceIdentifier.create(target.node(LocRib.QNAME).node(Tables.QNAME).node(tableKey).getPathArguments());
         this.ourAs = Preconditions.checkNotNull(ourAs);
+        this.service = Preconditions.checkNotNull(service);
         this.ribSupport = registry.getRIBSupportContext(tablesKey).getRibSupport();
         this.attributesIdentifier = this.ribSupport.routeAttributesIdentifier();
         this.exportPolicyPeerTracker = exportPolicyPeerTracker;
         this.pathSelectionMode = pathSelectionMode;
         this.routeCounter = routeCounter;
 
+        init();
+    }
+
+    private synchronized void init() {
         final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
         tx.merge(LogicalDatastoreType.OPERATIONAL, this.locRibTarget.node(Routes.QNAME), this.ribSupport.emptyRoutes());
-        tx.merge(LogicalDatastoreType.OPERATIONAL, this.locRibTarget.node(Attributes.QNAME).node(ATTRIBUTES_UPTODATE_TRUE.getNodeType()), ATTRIBUTES_UPTODATE_TRUE);
+        tx.merge(LogicalDatastoreType.OPERATIONAL, this.locRibTarget.node(Attributes.QNAME)
+            .node(ATTRIBUTES_UPTODATE_TRUE.getNodeType()), ATTRIBUTES_UPTODATE_TRUE);
         tx.submit();
 
-        final YangInstanceIdentifier tableId = target.node(Peer.QNAME).node(Peer.QNAME).node(EffectiveRibIn.QNAME).node(Tables.QNAME).node(tableKey);
+        final YangInstanceIdentifier tableId = this.target.node(Peer.QNAME).node(Peer.QNAME).node(EffectiveRibIn.QNAME)
+            .node(Tables.QNAME).node(this.tableKey);
         final DOMDataTreeIdentifier wildcard = new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, tableId);
-        this.reg = service.registerDataTreeChangeListener(wildcard, this);
+        this.reg = this.service.registerDataTreeChangeListener(wildcard, this);
     }
 
     public static LocRibWriter create(@Nonnull final RIBSupportContextRegistry registry, @Nonnull final TablesKey tablesKey, @Nonnull final DOMTransactionChain chain,
@@ -105,10 +117,22 @@ final class LocRibWriter implements AutoCloseable, ClusteredDOMDataTreeChangeLis
         return new LocRibWriter(registry, chain, target, ourAs.getValue(), service, ep, tablesKey, pathSelectionStrategy, routeCounter);
     }
 
+    /**
+     * Re-initialize this LocRibWriter with new transaction chain.
+     *
+     * @param newChain new transaction chain
+     */
+    synchronized void restart(@Nonnull final DOMTransactionChain newChain) {
+        Preconditions.checkNotNull(newChain);
+        close();
+        this.chain = newChain;
+        init();
+    }
+
     @Override
     public void close() {
         this.reg.close();
-        // FIXME: wait for the chain to close? unfortunately RIBImpl is the listener, so that may require some work
+        this.reg = null;
         this.chain.close();
     }