/* * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * * This file is part of PeerfactSim.KOM. * * PeerfactSim.KOM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * PeerfactSim.KOM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PeerfactSim.KOM. If not, see . * */ package de.tud.kom.p2psim.impl.topology; import java.util.LinkedHashMap; import java.util.Map; import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.linklayer.LinkLayer; import de.tud.kom.p2psim.api.linklayer.mac.PhyType; import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.TopologyComponent; import de.tud.kom.p2psim.api.topology.movement.MovementModel; import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel; import de.tud.kom.p2psim.api.topology.placement.PlacementModel; import de.tud.kom.p2psim.api.topology.social.SocialView; import de.tud.kom.p2psim.api.topology.views.TopologyView; import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel; import de.tud.kom.p2psim.impl.network.modular.DBHostListManager; import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; import de.tud.kom.p2psim.impl.topology.component.DefaultTopologyComponent; import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent; import de.tud.kom.p2psim.impl.topology.movement.AbstractWaypointMovementModel; import de.tud.kom.p2psim.impl.topology.movement.NoMovement; import de.tud.kom.p2psim.impl.topology.placement.GNPPlacement; import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tud.kom.p2psim.impl.topology.views.latency.GNPLatency; import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Host; import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; import de.tudarmstadt.maki.simonstrator.api.component.HostComponentFactory; import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; /** * This factory is configured with one or more {@link TopologyView}s if the * {@link LinkLayer} is used. * * @author Bjoern Richerzhagen, Julian Zobel * @version 1.1, 06.09.2018 */ public class TopologyFactory implements HostComponentFactory { private Topology topo; /** * Placement model for the current group of hosts */ private PlacementModel placement; /** * Movement model for the current group of hosts */ private MovementModel movement = new NoMovement(); private WaypointModel waypointModel; private ObstacleModel obstacleModel; private boolean registerAsInformationProviderInSiS = false; private static NetMeasurementDB measurementDB = null; private static Map measurementDBHosts = new LinkedHashMap(); private static DBHostListManager dbHostList = null; private static boolean useRegionGroups = false; private boolean alreadyCreatedInstances = false; private boolean alreadyAddedMovement = false; private boolean isUAVComponent = false; /** * */ @XMLConfigurableConstructor({ "worldX", "worldY" }) public TopologyFactory(double worldX, double worldY) { topo = new DefaultTopology(new PositionVector(worldX, worldY)); // Make the topology component available globally Binder.registerComponent(topo); } @Override public TopologyComponent createComponent(Host pHost) { alreadyCreatedInstances = true; SimHost host = (SimHost) pHost; if (measurementDB != null) { String groupStr = host.getProperties().getGroupID(); NetMeasurementDB.Host hostMeta; if (useRegionGroups) { // In case of a DB presence, look up the host's specific // metadata there NetMeasurementDB.Group g = measurementDB .getStringAddrObjFromStr(NetMeasurementDB.Group.class, groupStr); if (g == null) { throw new IllegalArgumentException( "There is no group named '" + groupStr + "'"); } hostMeta = g.tGetNextMember(); } else { // The hosts are not grouped by their region name, we will // return random hosts in the world for each group. hostMeta = dbHostList.getNextHost(); } measurementDBHosts.put(host, hostMeta); } /* * Create a TopologyComponent and register it with the Topology and its * movement model. */ TopologyComponent toCo; /* * Choose the UAV topology component, if this host is part of the UAV group! * */ if(isUAVComponent) { toCo = new UAVTopologyComponent(host, topo, movement, placement, registerAsInformationProviderInSiS); } else { toCo = new DefaultTopologyComponent(host, topo, movement, placement, registerAsInformationProviderInSiS); } /* * Need to register TopoViews as movement listeners, as they might need * to update topologies after each movement. */ for (PhyType phy : PhyType.values()) { TopologyView view = topo.getTopologyView(phy); if (view != null) { toCo.requestLocationUpdates(null, view); } } Monitor.log(TopologyFactory.class, Level.INFO, "Topology Component for Host %s created. Placement: %s, Movement: %s", host.getHostId(), placement, movement); return toCo; } /** * Set the {@link PlacementModel} for this group of hosts * * @param placementModel */ public void setPlacement(PlacementModel placementModel) { // Here, we loose the previous model. Intended! placement = placementModel; } public void setWaypoints(WaypointModel waypointModel) { waypointModel.setWorldDimensions(topo.getWorldDimensions()); this.waypointModel = waypointModel; this.waypointModel.setObstacleModel(this.obstacleModel); this.waypointModel.generateWaypoints(); topo.setWaypointModel(waypointModel); } public void setObstacles(ObstacleModel obstacleModel) { obstacleModel.setWorldDimensions(topo.getWorldDimensions()); this.obstacleModel = obstacleModel; this.obstacleModel.setWaypointModel(this.waypointModel); this.obstacleModel.generateObstacles(); topo.setObstacleModel(obstacleModel); } /** * Add a {@link TopologyView} * * @param topologyView */ public void setView(TopologyView topologyView) { if (alreadyCreatedInstances || alreadyAddedMovement) { throw new AssertionError( "Topology Views have to be specified globally, not in a host-section! " + "Furthermore, they have to be specified BEFORE the movement models!"); } topo.addTopologyView(topologyView); } public void setSocialView(SocialView sView) { topo.addSocialView(sView); } /** * Set the {@link MovementModel} for this group of hosts * * @param movement */ public void setMovement(MovementModel movement) { alreadyAddedMovement = true; if (movement instanceof AbstractWaypointMovementModel) { ((AbstractWaypointMovementModel) movement) .setWaypointModel(waypointModel); } this.movement = movement; } /** * For the {@link GNPLatency} and the {@link GNPPlacement}, a * {@link NetMeasurementDB} is needed. * * @param db */ public void setMeasurementDB(NetMeasurementDB db) { if (this.measurementDB == null) { this.measurementDB = db; this.dbHostList = new DBHostListManager(measurementDB); } else { throw new AssertionError( "You are only allowed to set the MeasurementDB once!"); } } public void setUseRegionGroups(boolean useRegionGroups) { TopologyFactory.useRegionGroups = useRegionGroups; } /** * Option to enable the behavior of nodes registering as * topology providers. * * @param registerAsLocationProviderInSiS */ public void setRegisterAsInformationProviderInSiS( boolean registerAsInformationProviderInSiS) { this.registerAsInformationProviderInSiS = registerAsInformationProviderInSiS; } /** * Allows GNP-based strategies to retrieve the unique * {@link NetMeasurementDB.Host} - as this object should only be created * once per host, it is maintained in this static manner. * * @param host * @return */ public static NetMeasurementDB.Host getMeasurementDBHost(SimHost host) { if (measurementDB == null) { throw new AssertionError(); } return measurementDBHosts.get(host); } /** * The Measurement-DB * * @return */ public static NetMeasurementDB getMeasurementDB() { if (measurementDB == null) { throw new AssertionError(); } return measurementDB; } public ObstacleModel getObstacleModel() { return obstacleModel; } public void setIsUAVComponent(boolean uav) { this.isUAVComponent = uav; } }