package org.dcache.services.topology; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Queue; import diskCacheV111.util.CacheException; import dmg.cells.network.CellDomainNode; import dmg.cells.nucleus.CellInfoProvider; import dmg.cells.nucleus.CellPath; import dmg.cells.nucleus.CellTunnelInfo; import dmg.cells.nucleus.NoRouteToCellException; import org.dcache.cells.CellStub; /** * Base class for CellsTopology implementations. Provides support for * building topology maps. */ public class AbstractCellsTopology implements CellInfoProvider { private static final Logger _log = LoggerFactory.getLogger(AbstractCellsTopology.class); private CellStub _stub; public void setCellStub(CellStub stub) { _stub = stub; } private CellTunnelInfo[] getCellTunnelInfos(String address) throws CacheException, InterruptedException, NoRouteToCellException { List<CellTunnelInfo> tunnels = new ArrayList<>(); _log.debug("Sending topology info request to " + address); CellTunnelInfo[] infos = _stub.sendAndWait(new CellPath(address), "getcelltunnelinfos", CellTunnelInfo[].class); _log.debug("Got reply from " + address); for (CellTunnelInfo info: infos) { if (info.getRemoteCellDomainInfo() != null) { tunnels.add(info); } } return tunnels.toArray(new CellTunnelInfo[tunnels.size()]); } private List<CellDomainNode> getConnectedNodes(CellDomainNode node) { List<CellDomainNode> nodes = new ArrayList<>(); for (CellTunnelInfo info: node.getLinks()) { String address = node.getAddress(); String domain = info.getRemoteCellDomainInfo().getCellDomainName(); nodes.add(new CellDomainNode(domain, address + ":System@" + domain)); } return nodes; } protected Map<String,CellDomainNode> buildTopologyMap(String domain) throws InterruptedException { Queue<CellDomainNode> queue = new ArrayDeque<>(); Map<String, CellDomainNode> map = new HashMap<>(); CellDomainNode node = new CellDomainNode(domain, "System@" + domain); queue.add(node); map.put(node.getName(), node); while ((node = queue.poll()) != null) { try { node.setLinks(getCellTunnelInfos(node.getAddress())); for (CellDomainNode connectedNode: getConnectedNodes(node)) { String name = connectedNode.getName(); if (!map.containsKey(name)) { queue.add(connectedNode); map.put(name, connectedNode); } } } catch (NoRouteToCellException | CacheException e) { _log.warn("Failed to fetch topology info from {}: {}", node.getAddress(), e.getMessage()); } } return map; } }