package org.opendaylight.protocol.bgp.config.loader.impl;
-import com.google.common.base.Preconditions;
+import static java.util.Objects.requireNonNull;
+
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.nio.file.ClosedWatchServiceException;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Map;
import java.util.regex.Pattern;
import javax.annotation.concurrent.GuardedBy;
+import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
import org.opendaylight.protocol.bgp.config.loader.spi.ConfigFileProcessor;
import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
public final class ConfigLoaderImpl implements ConfigLoader, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(ConfigLoaderImpl.class);
private static final String INTERRUPTED = "InterruptedException";
private final BindingNormalizedNodeSerializer bindingSerializer;
private final String path;
private final Thread watcherThread;
+ @GuardedBy("this")
+ private boolean closed = false;
public ConfigLoaderImpl(final SchemaContext schemaContext, final BindingNormalizedNodeSerializer bindingSerializer,
- final String path, final WatchService watchService) {
- this.schemaContext = Preconditions.checkNotNull(schemaContext);
- this.bindingSerializer = Preconditions.checkNotNull(bindingSerializer);
- this.path = Preconditions.checkNotNull(path);
- Preconditions.checkNotNull(watchService);
- this.watcherThread = new Thread(() -> {
- try {
- while (!Thread.currentThread().isInterrupted()) {
- try {
- final WatchKey key = watchService.take();
- if (key != null) {
- for (final WatchEvent event : key.pollEvents()) {
- handleEvent(event.context().toString());
- }
- final boolean reset = key.reset();
- if (!reset) {
- LOG.warn("Could not reset the watch key.");
- return;
- }
- }
- } catch (final InterruptedException e) {
- LOG.warn(INTERRUPTED, e);
- }
- }
- } catch (final Exception e) {
- LOG.warn(INTERRUPTED, e);
- }
- });
+ final String path, final WatchService watchService) {
+ this.schemaContext = requireNonNull(schemaContext);
+ this.bindingSerializer = requireNonNull(bindingSerializer);
+ this.path = requireNonNull(path);
+ requireNonNull(watchService);
+ this.watcherThread = new Thread(new ConfigLoaderImplRunnable(watchService));
this.watcherThread.start();
LOG.info("Config Loader service initiated");
}
final NormalizedNode<?, ?> dto;
try {
dto = parseDefaultConfigFile(config, filename);
- } catch (final Exception e) {
+ } catch (final IOException | XMLStreamException | ParserConfigurationException | SAXException
+ | URISyntaxException e) {
LOG.warn("Failed to parse config file {}", filename, e);
return;
}
config.loadConfiguration(dto);
}
- private NormalizedNode<?, ?> parseDefaultConfigFile(final ConfigFileProcessor config, final String filename) throws Exception {
+ private NormalizedNode<?, ?> parseDefaultConfigFile(final ConfigFileProcessor config, final String filename)
+ throws IOException, XMLStreamException, ParserConfigurationException, SAXException, URISyntaxException {
final NormalizedNodeResult result = new NormalizedNodeResult();
final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
return this.bindingSerializer;
}
- private synchronized void handleEvent(final String filename) {
- this.configServices.entrySet().stream().filter(entry -> Pattern.matches(entry.getKey(), filename)).
- forEach(entry -> handleConfigFile(entry.getValue(), filename));
- }
@Override
- public void close() throws Exception {
+ public synchronized void close() throws Exception {
+ LOG.info("Config Loader service closed");
+ this.closed = true;
this.watcherThread.interrupt();
}
-}
+
+ private class ConfigLoaderImplRunnable implements Runnable {
+ @GuardedBy("this")
+ private final WatchService watchService;
+
+ ConfigLoaderImplRunnable(final WatchService watchService) {
+ this.watchService = watchService;
+ }
+
+ @Override
+ public void run() {
+ while (!Thread.currentThread().isInterrupted()) {
+ handleChanges();
+ }
+ }
+
+ private synchronized void handleChanges() {
+ final WatchKey key;
+ try {
+ key = this.watchService.take();
+ } catch (final InterruptedException | ClosedWatchServiceException e) {
+ if (!ConfigLoaderImpl.this.closed) {
+ LOG.warn(INTERRUPTED, e);
+ Thread.currentThread().interrupt();
+ }
+ return;
+ }
+
+ if (key != null) {
+ for (final WatchEvent<?> event : key.pollEvents()) {
+ handleEvent(event.context().toString());
+ }
+ final boolean reset = key.reset();
+ if (!reset) {
+ LOG.warn("Could not reset the watch key.");
+ }
+ }
+ }
+
+ private synchronized void handleEvent(final String filename) {
+ ConfigLoaderImpl.this.configServices.entrySet().stream()
+ .filter(entry -> Pattern.matches(entry.getKey(), filename))
+ .forEach(entry -> handleConfigFile(entry.getValue(), filename));
+ }
+ }
+}
\ No newline at end of file
*/
package org.opendaylight.protocol.bgp.mode.impl.add;
+import static org.opendaylight.protocol.bgp.parser.spi.PathIdUtil.NON_PATH_ID;
+
import com.google.common.collect.Lists;
import com.google.common.primitives.UnsignedInteger;
import java.util.ArrayList;
if(this.removedPaths != null) {
this.removedPaths.forEach(removedPath -> {
final PathArgument routeIdAddPath = ribSupport.getRouteIdAddPath(removedPath.getPathId(), routeIdPA);
- fillAdjRibsOut(true, null, null, null, routeIdPA, routeIdAddPath, RouterIds.createPeerId(removedPath.getRouteId()),
- peerPT, localTK, ribSupport, tx);
+ final PathArgument routeIdAddPathDefault = ribSupport.getRouteIdAddPath(NON_PATH_ID, routeIdPA);
+ fillAdjRibsOut(true, null, null, null,
+ routeIdAddPathDefault, routeIdAddPath,
+ RouterIds.createPeerId(removedPath.getRouteId()), peerPT, localTK, ribSupport, tx);
});
this.removedPaths = null;
}
private void writeRoutePath(final PeerId destPeer, final PathArgument routeId, final ExportPolicyPeerTracker peerPT,
final PeerExportGroup peerGroup, final boolean destPeerSupAddPath,
final BestPath path, final YangInstanceIdentifier rootPath, final TablesKey localTK, final RIBSupport ribSup, final DOMDataWriteTransaction tx) {
- final PathArgument routeIdAddPath = ribSup.getRouteIdAddPath(path.getPathId(), routeId);
final ContainerNode effectiveAttributes = peerGroup.effectiveAttributes(getRoutePeerIdRole(peerPT,path.getPeerId()), path.getAttributes());
+ PathArgument routeIdAddPath;
if (destPeerSupAddPath) {
- writeRoute(destPeer, getAdjRibOutYII(ribSup, rootPath, routeIdAddPath, localTK), effectiveAttributes, createValue(routeIdAddPath, path), ribSup, tx);
+ routeIdAddPath = ribSup.getRouteIdAddPath(path.getPathId(), routeId);
} else {
- writeRoute(destPeer, getAdjRibOutYII(ribSup, rootPath, routeId, localTK), effectiveAttributes, createValue(routeId, path), ribSup, tx);
+ routeIdAddPath = ribSup.getRouteIdAddPath(NON_PATH_ID, routeId);
}
+ writeRoute(destPeer, getAdjRibOutYII(ribSup, rootPath, routeIdAddPath, localTK), effectiveAttributes,
+ createValue(routeIdAddPath, path), ribSup, tx);
}
- private void addPathToDataStore(final BestPath path, final boolean isFirstBestPath, final PathArgument routeIdPA, final YangInstanceIdentifier locRibTarget,
- final RIBSupport ribSup, final ExportPolicyPeerTracker peerPT, final TablesKey localTK, final DOMDataWriteTransaction tx) {
+ private void addPathToDataStore(final BestPath path, final boolean isFirstBestPath, final PathArgument routeIdPA,
+ final YangInstanceIdentifier locRibTarget, final RIBSupport ribSup, final ExportPolicyPeerTracker peerPT,
+ final TablesKey localTK, final DOMDataWriteTransaction tx) {
final PathArgument routeIdAddPath = ribSup.getRouteIdAddPath(path.getPathId(), routeIdPA);
- final YangInstanceIdentifier pathAddPathTarget = ribSup.routePath(locRibTarget.node(ROUTES_IDENTIFIER), routeIdAddPath);
+ final PathArgument routeIdAddPathDefault = ribSup.getRouteIdAddPath(NON_PATH_ID, routeIdPA);
+ final YangInstanceIdentifier pathAddPathTarget = ribSup.routePath(locRibTarget.node(ROUTES_IDENTIFIER),
+ routeIdAddPath);
+
final MapEntryNode addPathValue = createValue(routeIdAddPath, path);
- final MapEntryNode value = createValue(routeIdPA, path);
+ final MapEntryNode defaultValue = createValue(routeIdAddPathDefault, path);
LOG.trace("Selected best value {}", addPathValue);
fillLocRib(pathAddPathTarget, addPathValue, tx);
- fillAdjRibsOut(isFirstBestPath, path.getAttributes(), value, addPathValue, routeIdPA, routeIdAddPath, path.getPeerId(), peerPT, localTK,
- ribSup, tx);
+ fillAdjRibsOut(isFirstBestPath, path.getAttributes(), defaultValue, addPathValue, routeIdAddPathDefault,
+ routeIdAddPath, path.getPeerId(), peerPT, localTK, ribSup, tx);
}
- private void fillAdjRibsOut(final boolean isFirstBestPath, final ContainerNode attributes, final NormalizedNode<?, ?> value, final MapEntryNode addPathValue,
- final PathArgument routeId, final PathArgument routeIdAddPath, final PeerId routePeerId, final ExportPolicyPeerTracker peerPT, final TablesKey
- localTK, final RIBSupport ribSup, final DOMDataWriteTransaction tx) {
+ private void fillAdjRibsOut(final boolean isFirstBestPath, final ContainerNode attributes,
+ final MapEntryNode defaultValue, final MapEntryNode addPathValue,
+ final PathArgument routeIdAddPathDefault,
+ final PathArgument routeIdAddPath, final PeerId routePeerId, final ExportPolicyPeerTracker peerPT,
+ final TablesKey localTK, final RIBSupport ribSup, final DOMDataWriteTransaction tx) {
/*
* We need to keep track of routers and populate adj-ribs-out, too. If we do not, we need to
* expose from which client a particular route was learned from in the local RIB, and have
update(destPeer, getAdjRibOutYII(ribSup, rootPath, routeIdAddPath, localTK), effectiveAttributes,
addPathValue, ribSup, tx);
} else if(!this.oldNonAddPathBestPathTheSame){
- update(destPeer, getAdjRibOutYII(ribSup, rootPath, routeId, localTK), effectiveAttributes, value, ribSup, tx);
+ update(destPeer, getAdjRibOutYII(ribSup, rootPath, routeIdAddPathDefault, localTK), effectiveAttributes, defaultValue, ribSup, tx);
}
}
});
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
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.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
import org.slf4j.Logger;
final BaseBestPath newBestPath = selector.result();
final boolean modified = newBestPath == null || !newBestPath.equals(this.bestPath);
if (modified) {
- if(this.offsets.isEmpty()) {
+ if (this.offsets.isEmpty()) {
this.removedBestPath = this.bestPath;
}
LOG.trace("Previous best {}, current best {}", this.bestPath, newBestPath);
final BaseBestPath path = this.bestPath;
final PeerRole destPeerRole = getRoutePeerIdRole(peerPT, destPeer);
if (filterRoutes(path.getPeerId(), destPeer, peerPT, localTK, destPeerRole)) {
- final ContainerNode effAttrib = peerGroup.effectiveAttributes(getRoutePeerIdRole(peerPT,path.getPeerId()), path.getAttributes());
- writeRoute(destPeer, getAdjRibOutYII(ribSupport, rootPath, routeId, localTK), effAttrib,
- createValue(routeId, path), ribSupport, tx);
+ PathArgument routeIdDest = ribSupport.getRouteIdAddPath(path.getPathId(), routeId);
+ if (routeIdDest == null) {
+ routeIdDest = routeId;
+ }
+ final ContainerNode effAttrib = peerGroup.effectiveAttributes(getRoutePeerIdRole(peerPT, path.getPeerId()), path.getAttributes());
+ writeRoute(destPeer, getAdjRibOutYII(ribSupport, rootPath, routeIdDest, localTK), effAttrib,
+ createValue(routeIdDest, path), ribSupport, tx);
}
}
}
private void removePathFromDataStore(final BestPath path, final PathArgument routeIdPA, final YangInstanceIdentifier locRibTarget,
final ExportPolicyPeerTracker peerPT, final TablesKey localTK, final RIBSupport ribSup, final DOMDataWriteTransaction tx) {
LOG.trace("Best Path removed {}", path);
- final PathArgument routeIdAddPath = ribSup.getRouteIdAddPath(path.getPathId(), routeIdPA);
- final YangInstanceIdentifier pathTarget = ribSup.routePath(locRibTarget.node(ROUTES_IDENTIFIER), routeIdPA);
- YangInstanceIdentifier pathAddPathTarget = null;
- if (routeIdAddPath != null) {
- pathAddPathTarget = ribSup.routePath(locRibTarget.node(ROUTES_IDENTIFIER), routeIdAddPath);
+ PathArgument routeIdTarget = ribSup.getRouteIdAddPath(path.getPathId(), routeIdPA);
+ if (routeIdTarget == null) {
+ routeIdTarget = routeIdPA;
}
- fillLocRib(pathAddPathTarget == null ? pathTarget : pathAddPathTarget, null, tx);
- fillAdjRibsOut(null, null, routeIdPA, path.getPeerId(), peerPT, localTK, ribSup, tx);
+
+ fillLocRib(ribSup.routePath(locRibTarget.node(ROUTES_IDENTIFIER), routeIdTarget), null, tx);
+ fillAdjRibsOut(null, null, routeIdTarget, path.getPeerId(), peerPT, localTK, ribSup, tx);
}
private void addPathToDataStore(final BestPath path, final PathArgument routeIdPA, final YangInstanceIdentifier locRibTarget,
final RIBSupport ribSup, final ExportPolicyPeerTracker peerPT, final TablesKey localTK, final DOMDataWriteTransaction tx) {
- final PathArgument routeIdAddPath = ribSup.getRouteIdAddPath(path.getPathId(), routeIdPA);
- final YangInstanceIdentifier pathTarget = ribSup.routePath(locRibTarget.node(ROUTES_IDENTIFIER), routeIdPA);
- final NormalizedNode<?, ?> value = createValue(routeIdPA, path);
- NormalizedNode<?, ?> addPathValue = null;
- YangInstanceIdentifier pathAddPathTarget = null;
- if (routeIdAddPath == null) {
- LOG.trace("Selected best value {}", value);
- } else {
- pathAddPathTarget = ribSup.routePath(locRibTarget.node(ROUTES_IDENTIFIER), routeIdAddPath);
- addPathValue = createValue(routeIdAddPath, path);
- LOG.trace("Selected best value {}", addPathValue);
+ PathArgument routeIdDest = ribSup.getRouteIdAddPath(path.getPathId(), routeIdPA);
+ if (routeIdDest == null) {
+ routeIdDest = routeIdPA;
}
- fillLocRib(pathAddPathTarget == null ? pathTarget : pathAddPathTarget, addPathValue == null ? value : addPathValue, tx);
- fillAdjRibsOut(path.getAttributes(), value, routeIdPA, path.getPeerId(), peerPT, localTK, ribSup, tx);
+
+ final MapEntryNode value = createValue(routeIdDest, path);
+ LOG.trace("Selected best value {}", value);
+
+ final YangInstanceIdentifier pathAddPathTarget = ribSup.routePath(locRibTarget.node(ROUTES_IDENTIFIER), routeIdDest);
+ fillLocRib( pathAddPathTarget, value, tx);
+ fillAdjRibsOut(path.getAttributes(), value, routeIdDest, path.getPeerId(), peerPT, localTK, ribSup, tx);
}
final OffsetMap getOffsets() {
}
@VisibleForTesting
- private void fillAdjRibsOut(final ContainerNode attributes, final NormalizedNode<?, ?> value,
- final PathArgument routeId, final PeerId routePeerId, final ExportPolicyPeerTracker peerPT,
- final TablesKey localTK, final RIBSupport ribSup, final DOMDataWriteTransaction tx) {
+ private void fillAdjRibsOut(final ContainerNode attributes, final MapEntryNode value,
+ final PathArgument routeId, final PeerId routePeerId, final ExportPolicyPeerTracker peerPT,
+ final TablesKey localTK, final RIBSupport ribSup, final DOMDataWriteTransaction tx) {
/*
* We need to keep track of routers and populate adj-ribs-out, too. If we do not, we need to
* expose from which client a particular route was learned from in the local RIB, and have
protected static final NodeIdentifier ROUTES_IDENTIFIER = new NodeIdentifier(Routes.QNAME);
private static final Logger LOG = LoggerFactory.getLogger(AbstractRouteEntry.class);
- protected final void fillLocRib(final YangInstanceIdentifier routeTarget, final NormalizedNode<?, ?> value, final DOMDataWriteTransaction tx) {
+ protected static void fillLocRib(final YangInstanceIdentifier routeTarget, final NormalizedNode<?, ?> value,
+ final DOMDataWriteTransaction tx) {
if (value != null) {
LOG.debug("Write route to LocRib {}", value);
tx.put(LogicalDatastoreType.OPERATIONAL, routeTarget, value);
}
}
-
- protected final void update(final PeerId destPeer, final YangInstanceIdentifier routeTarget, final ContainerNode effAttr,
- final NormalizedNode<?, ?> value, final RIBSupport ribSup, final DOMDataWriteTransaction tx) {
+ protected static void update(final PeerId destPeer, final YangInstanceIdentifier routeTarget,
+ final ContainerNode effAttr, final NormalizedNode<?, ?> value, final RIBSupport ribSup,
+ final DOMDataWriteTransaction tx) {
if (!writeRoute(destPeer, routeTarget, effAttr, value, ribSup, tx)) {
deleteRoute(destPeer, routeTarget, tx);
}
}
- protected final boolean writeRoute(final PeerId destPeer, final YangInstanceIdentifier routeTarget, final ContainerNode effAttrib,
- final NormalizedNode<?, ?> value, final RIBSupport ribSup, final DOMDataWriteTransaction tx) {
+ protected static boolean writeRoute(final PeerId destPeer, final YangInstanceIdentifier routeTarget,
+ final ContainerNode effAttrib, final NormalizedNode<?, ?> value, final RIBSupport ribSup,
+ final DOMDataWriteTransaction tx) {
if (effAttrib != null && value != null) {
LOG.debug("Write route {} to peer AdjRibsOut {}", value, destPeer);
tx.put(LogicalDatastoreType.OPERATIONAL, routeTarget, value);
return false;
}
- private void deleteRoute(final PeerId destPeer, final YangInstanceIdentifier routeTarget, final DOMDataWriteTransaction tx) {
+ private static void deleteRoute(final PeerId destPeer, final YangInstanceIdentifier routeTarget,
+ final DOMDataWriteTransaction tx) {
LOG.trace("Removing {} from transaction for peer {}", routeTarget, destPeer);
tx.delete(LogicalDatastoreType.OPERATIONAL, routeTarget);
}
- protected final boolean filterRoutes(final PeerId rootPeer, final PeerId destPeer, final ExportPolicyPeerTracker peerPT, final TablesKey localTK, final PeerRole destPeerRole) {
+ protected static boolean filterRoutes(final PeerId rootPeer, final PeerId destPeer,
+ final ExportPolicyPeerTracker peerPT, final TablesKey localTK, final PeerRole destPeerRole) {
return !rootPeer.equals(destPeer) && isTableSupportedAndReady(destPeer, peerPT, localTK) && !PeerRole.Internal.equals(destPeerRole);
}
- private boolean isTableSupportedAndReady(final PeerId destPeer, final ExportPolicyPeerTracker peerPT, final TablesKey localTK) {
+ private static boolean isTableSupportedAndReady(final PeerId destPeer, final ExportPolicyPeerTracker peerPT, final TablesKey localTK) {
if (!peerPT.isTableSupported(destPeer) || !peerPT.isTableStructureInitialized(destPeer)) {
LOG.trace("Route rejected, peer {} does not support this table type {}", destPeer, localTK);
return false;
return true;
}
- protected final YangInstanceIdentifier getAdjRibOutYII(final RIBSupport ribSup, final YangInstanceIdentifier rootPath, final PathArgument routeId,
- final TablesKey localTK) {
+ protected static YangInstanceIdentifier getAdjRibOutYII(final RIBSupport ribSup,
+ final YangInstanceIdentifier rootPath, final PathArgument routeId, final TablesKey localTK) {
return ribSup.routePath(rootPath.node(AdjRibOut.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(localTK))
.node(ROUTES_IDENTIFIER), routeId);
}
- protected PeerRole getRoutePeerIdRole(final ExportPolicyPeerTracker peerPT, final PeerId routePeerId) {
+ protected static PeerRole getRoutePeerIdRole(final ExportPolicyPeerTracker peerPT, final PeerId routePeerId) {
for (final PeerRole role : PeerRole.values()) {
final PeerExportGroup peerGroup = peerPT.getPeerGroup(role);
- if(peerGroup != null && peerGroup.containsPeer(routePeerId)) {
+ if (peerGroup != null && peerGroup.containsPeer(routePeerId)) {
return role;
}
}
if (!table.getDataBefore().isPresent() && this.exportPolicyPeerTracker.isTableSupported(peerIdOfNewPeer)) {
this.exportPolicyPeerTracker.registerPeerAsInitialized(peerIdOfNewPeer);
LOG.debug("Peer {} table has been created, inserting existent routes", peerIdOfNewPeer);
+ if (this.routeEntries.isEmpty()) {
+ return;
+ }
final PeerRole newPeerRole = this.exportPolicyPeerTracker.getRole(IdentifierUtils.peerPath(rootPath));
final PeerExportGroup peerGroup = this.exportPolicyPeerTracker.getPeerGroup(newPeerRole);
this.routeEntries.entrySet().forEach(entry -> entry.getValue().writeRoute(peerIdOfNewPeer, entry.getKey(),