+ @Override
+ public boolean isSupported(final TablesKey tablesKey) {
+ return this.prefixesReceived.containsKey(tablesKey);
+ }
+
+ @Override
+ public long getPrefixedInstalledCount(final TablesKey tablesKey) {
+ final LongAdder counter = this.prefixesInstalled.get(tablesKey);
+ if (counter == null) {
+ return 0;
+ }
+ return counter.longValue();
+ }
+
+ @Override
+ public long getTotalPrefixesInstalled() {
+ return this.prefixesInstalled.values().stream().mapToLong(LongAdder::longValue).sum();
+ }
+
+ @Holding("this")
+ private void changeDataTree(final DOMDataTreeWriteTransaction tx, final YangInstanceIdentifier rootPath,
+ final DataTreeCandidateNode root, final DataTreeCandidateNode table) {
+ final PathArgument lastArg = table.getIdentifier();
+ verify(lastArg instanceof NodeIdentifierWithPredicates, "Unexpected type %s in path %s", lastArg.getClass(),
+ rootPath);
+ final NodeIdentifierWithPredicates tableKey = (NodeIdentifierWithPredicates) lastArg;
+ final RIBSupportContext ribContext = this.registry.getRIBSupportContext(tableKey);
+ if (ribContext == null) {
+ LOG.warn("Table {} is not supported, ignoring event", tableKey);
+ return;
+ }
+
+ final YangInstanceIdentifier effectiveTablePath = effectiveTablePath(tableKey);
+ final ModificationType modificationType = root.getModificationType();
+ LOG.debug("Effective table {} modification type {}", effectiveTablePath, modificationType);
+ switch (modificationType) {
+ case DISAPPEARED:
+ case DELETE:
+ deleteTable(tx, ribContext, effectiveTablePath, table);
+ break;
+ case APPEARED:
+ case WRITE:
+ writeTable(tx, ribContext, effectiveTablePath, table);
+ break;
+ case SUBTREE_MODIFIED:
+ modifyTable(tx, ribContext, effectiveTablePath, table);
+ break;
+ case UNMODIFIED:
+ LOG.info("Ignoring spurious notification on {} data {}", rootPath, table);
+ break;
+ default:
+ LOG.warn("Ignoring unhandled root {}", table);
+ break;
+ }
+ }
+
+ private void deleteTable(final DOMDataTreeWriteTransaction tx, final RIBSupportContext ribContext,
+ final YangInstanceIdentifier effectiveTablePath, final DataTreeCandidateNode table) {
+ LOG.debug("Delete Effective Table {}", effectiveTablePath);
+ onDeleteTable(ribContext.getRibSupport(), effectiveTablePath, table.getDataBefore());
+ tx.delete(LogicalDatastoreType.OPERATIONAL, effectiveTablePath);
+ }
+
+ private void modifyTable(final DOMDataTreeWriteTransaction tx, final RIBSupportContext ribContext,
+ final YangInstanceIdentifier effectiveTablePath, final DataTreeCandidateNode table) {
+ LOG.debug("Modify Effective Table {}", effectiveTablePath);
+
+ final boolean wasLongLivedStale = isLongLivedStaleTable(table.getDataBefore());
+ final boolean longLivedStale = isLongLivedStaleTable(table.getDataAfter());
+ if (wasLongLivedStale != longLivedStale) {
+ LOG.debug("LLGR_STALE flag flipped {}, overwriting table {}", longLivedStale ? "ON" : "OFF",
+ effectiveTablePath);
+ writeTable(tx, ribContext, effectiveTablePath, table);
+ return;
+ }
+
+ table.getModifiedChild(ATTRIBUTES_NID).ifPresent(modifiedAttrs -> {
+ final YangInstanceIdentifier effAttrsPath = effectiveTablePath.node(ATTRIBUTES_NID);
+ final Optional<NormalizedNode<?, ?>> optAttrsAfter = modifiedAttrs.getDataAfter();
+ if (optAttrsAfter.isPresent()) {
+ tx.put(LogicalDatastoreType.OPERATIONAL, effAttrsPath, effectiveAttributes(
+ NormalizedNodes.findNode(optAttrsAfter.get(), UPTODATE_NID)));
+ } else {
+ tx.delete(LogicalDatastoreType.OPERATIONAL, effAttrsPath);
+ }
+ });
+
+ table.getModifiedChild(ROUTES_NID).ifPresent(modifiedRoutes -> {
+ final RIBSupport<?, ?, ?, ?> ribSupport = ribContext.getRibSupport();
+ switch (modifiedRoutes.getModificationType()) {
+ case APPEARED: