*/
package org.opendaylight.protocol.bgp.rib.impl;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.dom.api.ClusteredDOMDataTreeChangeListener;
import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
-import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
+import org.opendaylight.protocol.bgp.rib.impl.spi.AbstractImportPolicy;
+import org.opendaylight.protocol.bgp.rib.impl.spi.ImportPolicyPeerTracker;
+import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
+import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
+import org.opendaylight.protocol.bgp.rib.impl.stats.peer.route.PerTableTypeRouteCounter;
+import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.graceful.restart._case.graceful.restart.capability.Tables;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.EffectiveRibIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Routes;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Implementation of the BGP import policy. Listens on all Adj-RIB-In, inspects all inbound
+ * Implementation of the BGP import policy. Listens on peer's Adj-RIB-In, inspects all inbound
* routes in the context of the advertising peer's role and applies the inbound policy.
*
* Inbound policy is applied as follows:
* advertising peer's role
* 3) output admitting routes with edited attributes into /bgp-rib/rib/peer/effective-rib-in/tables/routes
*
- * Note that we maintain the peer roles using a DCL, even if we could look up our internal
- * structures. This is done so we maintain causality and loose coupling.
*/
@NotThreadSafe
final class EffectiveRibInWriter implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(EffectiveRibInWriter.class);
- private static final NodeIdentifier TABLE_ROUTES = new NodeIdentifier(Routes.QNAME);
-
- /**
- * Maintains {@link TableRouteListener} instances.
- */
- private final class AdjInTracker implements AutoCloseable, DOMDataTreeChangeListener {
- private final RIBExtensionConsumerContext registry;
- private final YangInstanceIdentifier ribId;
+ protected static final NodeIdentifier TABLE_ROUTES = new NodeIdentifier(Routes.QNAME);
+
+ private final class AdjInTracker implements AutoCloseable, ClusteredDOMDataTreeChangeListener {
+ private final RIBSupportContextRegistry registry;
+ private final YangInstanceIdentifier peerIId;
+ private final YangInstanceIdentifier effRibTables;
private final ListenerRegistration<?> reg;
private final DOMTransactionChain chain;
+ private final PerTableTypeRouteCounter effectiveRibInRouteCounters;
+ private final PerTableTypeRouteCounter adjRibInRouteCounters;
+ private final Map<TablesKey, Set<YangInstanceIdentifier>> effectiveRibInRouteMap = new ConcurrentHashMap<>();
+ private final Map<TablesKey, Set<YangInstanceIdentifier>> adjRibInRouteMap = new ConcurrentHashMap<>();
- AdjInTracker(final DOMDataTreeChangeService service, final RIBExtensionConsumerContext registry, final DOMTransactionChain chain, final YangInstanceIdentifier ribId) {
+ AdjInTracker(final DOMDataTreeChangeService service, final RIBSupportContextRegistry registry, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId,
+ @Nonnull final PerTableTypeRouteCounter effectiveRibInRouteCounters, @Nonnull final PerTableTypeRouteCounter adjRibInRouteCounters) {
this.registry = Preconditions.checkNotNull(registry);
this.chain = Preconditions.checkNotNull(chain);
- this.ribId = Preconditions.checkNotNull(ribId);
+ this.peerIId = Preconditions.checkNotNull(peerIId);
+ this.effRibTables = this.peerIId.node(EffectiveRibIn.QNAME).node(Tables.QNAME);
+ this.effectiveRibInRouteCounters = Preconditions.checkNotNull(effectiveRibInRouteCounters);
+ this.adjRibInRouteCounters = Preconditions.checkNotNull(adjRibInRouteCounters);
- final YangInstanceIdentifier tableId = ribId.node(Peer.QNAME).node(AdjRibIn.QNAME).node(Tables.QNAME);
- final DOMDataTreeIdentifier treeId = new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, tableId);
+ final DOMDataTreeIdentifier treeId = new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, this.peerIId.node(AdjRibIn.QNAME).node(Tables.QNAME));
+ LOG.debug("Registered Effective RIB on {}", this.peerIId);
this.reg = service.registerDataTreeChangeListener(treeId, this);
}
+ /**
+ * @deprecated Should always pass in route counter
+ * @param service
+ * @param registry
+ * @param chain
+ * @param peerIId
+ */
+ @Deprecated
+ AdjInTracker(final DOMDataTreeChangeService service, final RIBSupportContextRegistry registry, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId) {
+ this(service, registry, chain, peerIId, new PerTableTypeRouteCounter("effective-rib-in"), new PerTableTypeRouteCounter("adj-rib-in"));
+ }
+
+ private void updateRoute(@Nonnull final PerTableTypeRouteCounter counter, @Nonnull final Map<TablesKey, Set<YangInstanceIdentifier>> routeMap,
+ @Nonnull final TablesKey tablesKey, @Nonnull final YangInstanceIdentifier routeId) {
+ routeMap.putIfAbsent(tablesKey, new HashSet<>());
+ routeMap.get(tablesKey).add(routeId);
+
+ updateRouteCounter(counter, routeMap,tablesKey);
+ }
+
+ private void deleteRoute(@Nonnull final PerTableTypeRouteCounter counter, @Nonnull final Map<TablesKey, Set<YangInstanceIdentifier>> routeMap,
+ @Nonnull final TablesKey tablesKey, @Nonnull final YangInstanceIdentifier routeId) {
+ if (routeMap.containsKey(tablesKey)) {
+ routeMap.get(tablesKey).remove(routeId);
+ }
+
+ updateRouteCounter(counter, routeMap,tablesKey);
+ }
+
+ private void deleteRoute(@Nonnull final PerTableTypeRouteCounter counter, @Nonnull final Map<TablesKey, Set<YangInstanceIdentifier>> routeMap,
+ @Nonnull final TablesKey tablesKey) {
+ routeMap.remove(tablesKey);
+
+ updateRouteCounter(counter, routeMap,tablesKey);
+ }
+
+ private void updateRouteCounter(@Nonnull final PerTableTypeRouteCounter counter, @Nonnull final Map<TablesKey, Set<YangInstanceIdentifier>> routeMap,
+ @Nonnull final TablesKey tablesKey) {
+ counter.getCounterOrSetDefault(tablesKey)
+ .setCount(routeMap.getOrDefault(tablesKey, new HashSet<>()).size());
+ }
+
private void processRoute(final DOMDataWriteTransaction tx, final RIBSupport ribSupport, final AbstractImportPolicy policy, final YangInstanceIdentifier routesPath, final DataTreeCandidateNode route) {
+ LOG.debug("Process route {}", route.getIdentifier());
+ final YangInstanceIdentifier routeId = ribSupport.routePath(routesPath, route.getIdentifier());
+ final TablesKey tablesKey = new TablesKey(ribSupport.getAfi(), ribSupport.getSafi());
switch (route.getModificationType()) {
case DELETE:
- // Delete has already been affected by the store in caller, so this is a no-op.
- break;
- case MERGE:
- LOG.info("Merge on {} reported, this should never have happened, ignoring", route);
+ case DISAPPEARED:
+ tx.delete(LogicalDatastoreType.OPERATIONAL, routeId);
+ LOG.debug("Route deleted. routeId={}", routeId);
+
+ deleteRoute(this.adjRibInRouteCounters, this.adjRibInRouteMap, tablesKey, routeId);
+ deleteRoute(this.effectiveRibInRouteCounters, this.effectiveRibInRouteMap, tablesKey, routeId);
break;
case UNMODIFIED:
// No-op
break;
+ case APPEARED:
case SUBTREE_MODIFIED:
case WRITE:
+ tx.put(LogicalDatastoreType.OPERATIONAL, routeId, route.getDataAfter().get());
+ // count adj-rib-in route first
+ updateRoute(this.adjRibInRouteCounters, this.adjRibInRouteMap, tablesKey, routeId);
+ updateRoute(this.effectiveRibInRouteCounters, this.effectiveRibInRouteMap, tablesKey, routeId);
// Lookup per-table attributes from RIBSupport
- final ContainerNode adverisedAttrs = (ContainerNode) NormalizedNodes.findNode(route.getDataAfter(), ribSupport.routeAttributesIdentifier()).orNull();
+ final ContainerNode advertisedAttrs = (ContainerNode) NormalizedNodes.findNode(route.getDataAfter(), ribSupport.routeAttributesIdentifier()).orNull();
final ContainerNode effectiveAttrs;
- if (adverisedAttrs != null) {
- effectiveAttrs = policy.effectiveAttributes(adverisedAttrs);
-
- /*
- * Speed hack: if we determine that the policy has passed the attributes
- * back unmodified, the corresponding change has already been written in
- * our caller. There is no need to perform any further processing.
- *
- * We also use direct object comparison to make the check very fast, as
- * it may not be that common, in which case it does not make sense to pay
- * the full equals price.
- */
- if (effectiveAttrs == adverisedAttrs) {
- return;
- }
+ if (advertisedAttrs != null) {
+ effectiveAttrs = policy.effectiveAttributes(advertisedAttrs);
} else {
effectiveAttrs = null;
}
- final YangInstanceIdentifier routeId = ribSupport.routePath(routesPath, route.getIdentifier());
LOG.debug("Route {} effective attributes {} towards {}", route.getIdentifier(), effectiveAttrs, routeId);
if (effectiveAttrs != null) {
tx.put(LogicalDatastoreType.OPERATIONAL, routeId.node(ribSupport.routeAttributesIdentifier()), effectiveAttrs);
+
+ updateRoute(this.effectiveRibInRouteCounters, this.effectiveRibInRouteMap, tablesKey, routeId);
} else {
- LOG.warn("Route {} advertised empty attributes", route.getDataAfter());
+ LOG.warn("Route {} advertised empty attributes", routeId);
tx.delete(LogicalDatastoreType.OPERATIONAL, routeId);
+
+ deleteRoute(this.effectiveRibInRouteCounters, this.effectiveRibInRouteMap, tablesKey, routeId);
}
break;
default:
}
}
- private void processTableChildren(final DOMDataWriteTransaction tx, final RIBSupport ribSupport, final AbstractImportPolicy policy, final YangInstanceIdentifier tablePath, final Collection<DataTreeCandidateNode> children) {
- for (DataTreeCandidateNode child : children) {
+ private void processTableChildren(final DOMDataWriteTransaction tx, final RIBSupport ribSupport, final YangInstanceIdentifier tablePath, final Collection<DataTreeCandidateNode> children) {
+ for (final DataTreeCandidateNode child : children) {
+ final PathArgument childIdentifier = child.getIdentifier();
+ final Optional<NormalizedNode<?, ?>> childDataAfter = child.getDataAfter();
+ final TablesKey tablesKey = new TablesKey(ribSupport.getAfi(), ribSupport.getSafi());
+ LOG.debug("Process table {} type {}, dataAfter {}, dataBefore {}", childIdentifier, child
+ .getModificationType(), childDataAfter, child.getDataBefore());
+ final YangInstanceIdentifier childPath = tablePath.node(childIdentifier);
switch (child.getModificationType()) {
case DELETE:
- tx.delete(LogicalDatastoreType.OPERATIONAL, tablePath.node(child.getIdentifier()));
- break;
- case MERGE:
- LOG.info("Merge on {} reported, this should never have happened, ignoring", child);
+ case DISAPPEARED:
+ tx.delete(LogicalDatastoreType.OPERATIONAL, childPath);
+ LOG.debug("Route deleted. routeId={}", childPath);
+
+ deleteRoute(this.adjRibInRouteCounters, this.adjRibInRouteMap, tablesKey, childPath);
+ deleteRoute(this.effectiveRibInRouteCounters, this.effectiveRibInRouteMap, tablesKey, childPath);
break;
case UNMODIFIED:
// No-op
break;
case SUBTREE_MODIFIED:
+ processModifiedRouteTables(child, childIdentifier,tx, ribSupport, EffectiveRibInWriter.this.importPolicy, childPath, childDataAfter);
+ break;
+ case APPEARED:
case WRITE:
- tx.put(LogicalDatastoreType.OPERATIONAL, tablePath.node(child.getIdentifier()), child.getDataAfter().get());
+ writeRouteTables(child, childIdentifier,tx, ribSupport, EffectiveRibInWriter.this.importPolicy, childPath, childDataAfter);
- // Routes are special, as they may end up being filtered. The previous put conveniently
- // ensured that we have them in at target, so a subsequent delete will not fail :)
- if (TABLE_ROUTES.equals(child.getIdentifier())) {
- final YangInstanceIdentifier routesPath = tablePath.node(Routes.QNAME);
- for (DataTreeCandidateNode route : ribSupport.changedRoutes(child)) {
- processRoute(tx, ribSupport, policy, routesPath, route);
- }
- }
break;
default:
LOG.warn("Ignoring unhandled child {}", child);
}
}
- private RIBSupport getRibSupport(final NodeIdentifierWithPredicates tableKey) {
- // FIXME: use codec to translate tableKey
- return registry.getRIBSupport(null);
+ private void processModifiedRouteTables(final DataTreeCandidateNode child, final PathArgument childIdentifier, final DOMDataWriteTransaction tx,
+ final RIBSupport ribSupport, final AbstractImportPolicy policy, final YangInstanceIdentifier childPath, final Optional<NormalizedNode<?, ?>> childDataAfter) {
+ if (TABLE_ROUTES.equals(childIdentifier)) {
+ for (final DataTreeCandidateNode route : ribSupport.changedRoutes(child)) {
+ processRoute(tx, ribSupport, policy, childPath, route);
+ }
+ } else {
+ tx.put(LogicalDatastoreType.OPERATIONAL, childPath, childDataAfter.get());
+ }
+ }
+
+ private void writeRouteTables(final DataTreeCandidateNode child, final PathArgument childIdentifier, final DOMDataWriteTransaction tx, final RIBSupport ribSupport, final AbstractImportPolicy policy, final YangInstanceIdentifier childPath, final Optional<NormalizedNode<?, ?>> childDataAfter) {
+ if (TABLE_ROUTES.equals(childIdentifier)) {
+ final Collection<DataTreeCandidateNode> changedRoutes = ribSupport.changedRoutes(child);
+ if (!changedRoutes.isEmpty()) {
+ tx.put(LogicalDatastoreType.OPERATIONAL, childPath, childDataAfter.get());
+ // Routes are special, as they may end up being filtered. The previous put conveniently
+ // ensured that we have them in at target, so a subsequent delete will not fail :)
+ for (final DataTreeCandidateNode route : changedRoutes) {
+ processRoute(tx, ribSupport, policy, childPath, route);
+ }
+ }
+ }
+ }
+
+ private RIBSupportContext getRibSupport(final NodeIdentifierWithPredicates tableKey) {
+ return this.registry.getRIBSupportContext(tableKey);
}
- private YangInstanceIdentifier effectiveTablePath(final NodeIdentifierWithPredicates peerKey, final NodeIdentifierWithPredicates tableKey) {
- return ribId.node(peerKey).node(EffectiveRibIn.QNAME).node(tableKey);
+ private YangInstanceIdentifier effectiveTablePath(final NodeIdentifierWithPredicates tableKey) {
+ return this.effRibTables.node(tableKey);
}
- private void modifyTable(final DOMDataWriteTransaction tx, final NodeIdentifierWithPredicates peerKey, final NodeIdentifierWithPredicates tableKey, final DataTreeCandidateNode table) {
- final RIBSupport ribSupport = getRibSupport(tableKey);
- final YangInstanceIdentifier tablePath = effectiveTablePath(peerKey, tableKey);
+ private void modifyTable(final DOMDataWriteTransaction tx, final NodeIdentifierWithPredicates tableKey, final DataTreeCandidateNode table) {
+ final RIBSupportContext ribSupport = getRibSupport(tableKey);
+ final YangInstanceIdentifier tablePath = effectiveTablePath(tableKey);
- final AbstractImportPolicy policy = peerPolicyTracker.policyFor(IdentifierUtils.peerId(peerKey));
- processTableChildren(tx, ribSupport, policy, tablePath, table.getChildNodes());
+ processTableChildren(tx, ribSupport.getRibSupport(), tablePath, table.getChildNodes());
}
- private void writeTable(final DOMDataWriteTransaction tx, final NodeIdentifierWithPredicates peerKey, final NodeIdentifierWithPredicates tableKey, final DataTreeCandidateNode table) {
- final RIBSupport ribSupport = getRibSupport(tableKey);
- final YangInstanceIdentifier tablePath = effectiveTablePath(peerKey, tableKey);
+ private void writeTable(final DOMDataWriteTransaction tx, final NodeIdentifierWithPredicates tableKey, final DataTreeCandidateNode table) {
+ final RIBSupportContext ribSupport = getRibSupport(tableKey);
+ final YangInstanceIdentifier tablePath = effectiveTablePath(tableKey);
// Create an empty table
- TableContext.clearTable(tx, ribSupport, tablePath);
+ LOG.trace("Create Empty table", tablePath);
+ ribSupport.createEmptyTableStructure(tx, tablePath);
- final AbstractImportPolicy policy = peerPolicyTracker.policyFor(IdentifierUtils.peerId(peerKey));
- processTableChildren(tx, ribSupport, policy, tablePath, table.getChildNodes());
+ processTableChildren(tx, ribSupport.getRibSupport(), tablePath, table.getChildNodes());
}
@Override
- public void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
- final DOMDataWriteTransaction tx = chain.newWriteOnlyTransaction();
+ public void onDataTreeChanged(@Nonnull final Collection<DataTreeCandidate> changes) {
+ LOG.trace("Data changed called to effective RIB. Change : {}", changes);
- for (DataTreeCandidate tc : changes) {
+ // we have a lot of transactions created for 'nothing' because a lot of changes
+ // are skipped, so ensure we only create one transaction when we really need it
+ DOMDataWriteTransaction tx = null;
+ for (final DataTreeCandidate tc : changes) {
final YangInstanceIdentifier rootPath = tc.getRootPath();
- // Obtain the peer's key
- final NodeIdentifierWithPredicates peerKey = IdentifierUtils.peerKey(rootPath);
-
- // Extract the table key, this should be safe based on the path where we subscribed,
- // but let's verify explicitly.
- final PathArgument lastArg = rootPath.getLastPathArgument();
- Verify.verify(lastArg instanceof NodeIdentifierWithPredicates, "Unexpected type %s in path %s", lastArg.getClass(), rootPath);
- final NodeIdentifierWithPredicates tableKey = (NodeIdentifierWithPredicates) lastArg;
-
final DataTreeCandidateNode root = tc.getRootNode();
- switch (root.getModificationType()) {
- case DELETE:
- // delete the corresponding effective table
- tx.delete(LogicalDatastoreType.OPERATIONAL, effectiveTablePath(peerKey, tableKey));
- break;
- case MERGE:
- // TODO: upstream API should never give us this, as it leaks how the delta was created.
- LOG.info("Merge on {} reported, this should never have happened, but attempting to cope", rootPath);
- modifyTable(tx, peerKey, tableKey, root);
- break;
- case SUBTREE_MODIFIED:
- modifyTable(tx, peerKey, tableKey, root);
- break;
- case UNMODIFIED:
- LOG.info("Ignoring spurious notification on {} data {}", rootPath, root);
- break;
- case WRITE:
- writeTable(tx, peerKey, tableKey, root);
- break;
- default:
- LOG.warn("Ignoring unhandled root {}", root);
- break;
+ for (final DataTreeCandidateNode table : root.getChildNodes()) {
+ if (tx == null) {
+ tx = this.chain.newWriteOnlyTransaction();
+ }
+ changeDataTree(tx, rootPath, root, table);
}
}
+ if (tx != null) {
+ tx.submit();
+ }
+ }
+
+ private void changeDataTree(final DOMDataWriteTransaction tx, final YangInstanceIdentifier rootPath,
+ final DataTreeCandidateNode root, final DataTreeCandidateNode table) {
+ final PathArgument lastArg = table.getIdentifier();
+ Verify.verify(lastArg instanceof NodeIdentifierWithPredicates, "Unexpected type %s in path %s", lastArg.getClass(), rootPath);
+ final NodeIdentifierWithPredicates tableKey = (NodeIdentifierWithPredicates) lastArg;
+ final RIBSupport ribSupport = getRibSupport(tableKey).getRibSupport();
+ final ModificationType modificationType = root.getModificationType();
+ switch (modificationType) {
+ case DELETE:
+ case DISAPPEARED:
+ final YangInstanceIdentifier effectiveTablePath = effectiveTablePath(tableKey);
+ LOG.debug("Delete Effective Table {} modification type {}, ", effectiveTablePath, modificationType);
+
+ // delete the corresponding effective table
+ tx.delete(LogicalDatastoreType.OPERATIONAL, effectiveTablePath);
- tx.submit();
+ deleteRoute(this.adjRibInRouteCounters, this.adjRibInRouteMap, new TablesKey(ribSupport.getAfi(), ribSupport.getSafi()));
+ deleteRoute(this.effectiveRibInRouteCounters, this.effectiveRibInRouteMap, new TablesKey(ribSupport.getAfi(), ribSupport.getSafi()));
+ break;
+ case SUBTREE_MODIFIED:
+ modifyTable(tx, tableKey, table);
+ break;
+ case UNMODIFIED:
+ LOG.info("Ignoring spurious notification on {} data {}", rootPath, table);
+ break;
+ case APPEARED:
+ case WRITE:
+ writeTable(tx, tableKey, table);
+ break;
+ default:
+ LOG.warn("Ignoring unhandled root {}", root);
+ break;
+ }
}
@Override
public void close() {
- // FIXME: wipe all effective routes?
- reg.close();
+ this.reg.close();
}
}
- private final ImportPolicyPeerTracker peerPolicyTracker;
private final AdjInTracker adjInTracker;
+ private final AbstractImportPolicy importPolicy;
+
+ @Deprecated
+ static EffectiveRibInWriter create(@Nonnull final DOMDataTreeChangeService service, @Nonnull final DOMTransactionChain chain,
+ @Nonnull final YangInstanceIdentifier peerIId, @Nonnull final ImportPolicyPeerTracker importPolicyPeerTracker, @Nonnull final RIBSupportContextRegistry registry, final PeerRole peerRole) {
+ return new EffectiveRibInWriter(service, chain, peerIId, importPolicyPeerTracker, registry, peerRole);
+ }
+
+ static EffectiveRibInWriter create(@Nonnull final DOMDataTreeChangeService service, @Nonnull final DOMTransactionChain chain,
+ @Nonnull final YangInstanceIdentifier peerIId, @Nonnull final ImportPolicyPeerTracker importPolicyPeerTracker, @Nonnull final RIBSupportContextRegistry registry, final PeerRole peerRole,
+ @Nonnull final PerTableTypeRouteCounter effectiveRouteCounters, @Nonnull final PerTableTypeRouteCounter adjRibInRouteCounters) {
+ return new EffectiveRibInWriter(service, chain, peerIId, importPolicyPeerTracker, registry, peerRole, effectiveRouteCounters, adjRibInRouteCounters);
+ }
+
+ @Deprecated
+ private EffectiveRibInWriter(final DOMDataTreeChangeService service, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId,
+ final ImportPolicyPeerTracker importPolicyPeerTracker, final RIBSupportContextRegistry registry, final PeerRole peerRole) {
+ importPolicyPeerTracker.peerRoleChanged(peerIId, peerRole);
+ this.importPolicy = importPolicyPeerTracker.policyFor(IdentifierUtils.peerId((NodeIdentifierWithPredicates) peerIId.getLastPathArgument()));
+ this.adjInTracker = new AdjInTracker(service, registry, chain, peerIId);
+ }
- private EffectiveRibInWriter(final DOMDataTreeChangeService service, final DOMTransactionChain chain, final YangInstanceIdentifier ribId) {
- this.peerPolicyTracker = new ImportPolicyPeerTracker(service, ribId);
- // FIXME: proper argument
- this.adjInTracker = new AdjInTracker(service, null, chain, ribId);
+ private EffectiveRibInWriter(final DOMDataTreeChangeService service, final DOMTransactionChain chain, final YangInstanceIdentifier peerIId,
+ final ImportPolicyPeerTracker importPolicyPeerTracker, final RIBSupportContextRegistry registry, final PeerRole peerRole,
+ @Nonnull final PerTableTypeRouteCounter effectiveRouteCounters, @Nonnull final PerTableTypeRouteCounter adjRibInRouteCounters) {
+ importPolicyPeerTracker.peerRoleChanged(peerIId, peerRole);
+ this.importPolicy = importPolicyPeerTracker.policyFor(IdentifierUtils.peerId((NodeIdentifierWithPredicates) peerIId.getLastPathArgument()));
+ this.adjInTracker = new AdjInTracker(service, registry, chain, peerIId, effectiveRouteCounters, adjRibInRouteCounters);
}
@Override
public void close() {
- adjInTracker.close();
- peerPolicyTracker.close();
+ this.adjInTracker.close();
}
}