/** * To debug the player * * @author Leo Nobach <*****@*****.**> * @version 05/06/2011 */ public class ConsolePlayerNotifier implements PlayerEventListener { private static Logger log = SimLogger.getLogger(PlayerEventListener.class); @Override public void forward() { log.debug("PLAYER: Forward"); } @Override public void pause() { log.debug("PLAYER: Pause"); } @Override public void play() { log.debug("PLAYER: Play"); } @Override public void reverse() { log.debug("PLAYER: Reverse"); } @Override public void stop() { log.debug("PLAYER: Stop"); } @Override public void speedChange(double speed) { log.debug("Speed Change: " + speed + "ms"); } @Override public void quantizationChange(double quantization) { log.debug("Quantization Change: " + quantization + "ms"); } }
/** * This class manages the mapping of the 2-digits country code to country and region used in the * aggregated PingEr reports. * * @author Gerald Klunker <*****@*****.**> * @version 0.1, 09.01.2008 */ public class CountryLookup implements Serializable { private static final long serialVersionUID = -3994762133062677848L; private static Logger log = SimLogger.getLogger(CountryLookup.class); private LinkedHashMap<String, String[]> countryLookup = new LinkedHashMap<String, String[]>(); private LinkedHashMap<String, String> pingErCountryRegions = new LinkedHashMap<String, String>(); private String pingErCountryRegionFilename; // sorted list holding PingEr Data for using in a graphical frontend only private ArrayList<String> pingErCountry = new ArrayList<String>(); private ArrayList<String> pingErRegion = new ArrayList<String>(); /** * @param 2-digits country code * @return dedicated GeoIP country name */ public String getGeoIpCountryName(String countryCode) { if (countryLookup.containsKey(countryCode)) { return countryLookup.get(countryCode)[0]; } else { return null; } } /** * @param 2-digits country code * @return dedicated PingEr country name */ public String getPingErCountryName(String countryCode) { if (countryLookup.containsKey(countryCode)) { return countryLookup.get(countryCode)[1]; } else { return null; } } /** * @param country 2-digits country code or pingEr country name * @return dedicated PingEr region name */ public String getPingErRegionName(String country) { if (countryLookup.containsKey(country)) { return countryLookup.get(country)[2]; } else if (pingErCountryRegions.containsKey(country)) { return pingErCountryRegions.get(country); } return null; } /** * Adds GeoIP country code and country name. * * <p>It will be assign automatically to PingEr Countries, if there are obvious consenses. * * @param 2-digits country code * @param dedicated country name from GeoIP */ public void addCountryFromGeoIP(String countryCode, String country) { if (!countryLookup.containsKey(countryCode)) { String[] names = new String[3]; names[0] = country; if (pingErCountryRegions.containsKey(country)) { names[1] = country; names[2] = pingErCountryRegions.get(country); } countryLookup.put(countryCode, names); } } /** * Assign a country code (from GeoIP) to PingER country and/or region name. Attention: Nothing * happens, if country code was not added before * * @param 2-digits country code * @param dedicated country name from PingER * @param dedicated region name from PingER */ public void assignCountryCodeToPingErData(String code, String country, String region) { if (countryLookup.containsKey(code)) { String[] names = countryLookup.get(code); names[1] = country; names[2] = region; } } /** * Import all country and region names, that are used by the PingER Project. The Country - Region * Mapping File can be downloaded form the website of the project. * (http://www-iepm.slac.stanford.edu/pinger/region_country.txt) * * <p>GeoIP countries will be assign automatically to PingEr Countries, if there are obviouse * consensuses. * * @param file */ public void importPingErCountryRegionFile(File file) { try { log.debug("Importing PingER-Country-Region-File: " + file.getAbsolutePath()); FileReader inputFilePingER = new FileReader(file); BufferedReader inputPingER = new BufferedReader(inputFilePingER); LinkedHashMap<String, String> countryToRegion = new LinkedHashMap<String, String>(); String line = inputPingER.readLine(); while (line != null) { String[] parts = line.split(","); countryToRegion.put(parts[0], parts[1]); line = inputPingER.readLine(); } inputPingER.close(); inputFilePingER.close(); Set<String> codes = countryLookup.keySet(); for (String cc : codes) { String geoIpCountry = getGeoIpCountryName(cc); if (geoIpCountry != null && countryToRegion.containsKey(geoIpCountry)) { assignCountryCodeToPingErData(cc, geoIpCountry, countryToRegion.get(geoIpCountry)); } } pingErCountryRegions.putAll(countryToRegion); this.pingErCountryRegionFilename = file.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); } } /** * Import lockup data from an xml-element. * * @param element */ public void importFromXML(Element element) { Iterator<Element> iter = element.elementIterator("CountryKey"); while (iter.hasNext()) { Element variable = iter.next(); String code = variable.attributeValue("code"); String[] names = new String[3]; names[0] = variable.attributeValue("countryGeoIP"); names[1] = variable.attributeValue("countryPingEr"); names[2] = variable.attributeValue("regionPingEr"); countryLookup.put(code, names); pingErCountryRegions.put(names[1], names[2]); } } /** * Import lockup data from an xml-file. * * @param file */ public void importFromXML(File file) { try { SAXReader reader = new SAXReader(false); Document configuration = reader.read(file); Element root = configuration.getRootElement(); importFromXML(root); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** @return xml-element containing current lookup data */ public Element exportToXML() { DefaultElement country = new DefaultElement("CountryLookup"); Set<String> codeKeys = countryLookup.keySet(); for (String code : codeKeys) { DefaultElement countryXml = new DefaultElement("CountryKey"); countryXml.addAttribute("code", code); countryXml.addAttribute("countryGeoIP", getGeoIpCountryName(code)); countryXml.addAttribute("countryPingEr", getPingErCountryName(code)); countryXml.addAttribute("regionPingEr", getPingErRegionName(code)); country.add(countryXml); } return country; } /** @return set of all available country codes added */ public Set<String> getCountryCodes() { return countryLookup.keySet(); } /** @return sorted list of all available PingEr country names */ public ArrayList<String> getPingErCountrys() { if (pingErCountry.size() <= 1) { pingErCountry.clear(); pingErCountry.addAll(pingErCountryRegions.keySet()); pingErCountry.add(""); Collections.sort(pingErCountry); } return pingErCountry; } /** @return sorted list of all available PingEr region names */ public ArrayList<String> getPingErRegions() { if (pingErRegion.size() <= 1) { pingErRegion.clear(); Set<String> region = new LinkedHashSet<String>(); region.addAll(pingErCountryRegions.values()); pingErRegion.addAll(region); pingErRegion.add(""); Collections.sort(pingErRegion); } return pingErRegion; } /** * Remove all countries that are not defined in the Set * * @param countryCodes Set of country codes */ public void keepCountries(Set<String> countryCodes) { countryLookup.keySet().retainAll(countryCodes); } /** * @param name of country or region * @return true, if there is a country or region with name exist */ public boolean containsPingErCountryOrRegion(String name) { for (String[] names : countryLookup.values()) { if (names[1] != null && names[1].equals(name)) { return true; } if (names[2] != null && names[2].equals(name)) { return true; } } return false; } /** @return PingER Country - Region Mapping Filename (region_country.txt) used for naming */ public String getPingErCountryRegionFilename() { return pingErCountryRegionFilename; } }
/** * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! This part of the * Simulator is not maintained in the current version of PeerfactSim.KOM. There is no intention of * the authors to fix this circumstances, since the changes needed are huge compared to overall * benefit. * * <p>If you want it to work correctly, you are free to make the specific changes and provide it to * the community. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! * * <p>This class implements the calculation of the position of a SkyNet-node in the SkyNet-tree and * retrieves the information of the determined Parent-Coordinator. * * @author Dominik Stingl <*****@*****.**> * @version 1.0, 04.12.2008 */ public class TreeHandler { private static Logger log = SimLogger.getLogger(TreeHandler.class); private boolean isRoot; private SkyNetNodeInfo parentCoordinator; private final SkyNetNodeInterface skyNetNode; private SkyNetID coordinatorKey; private int level; private final int branchingFactor; private final TreeHandlerDelegator treeHandlerDelegator; public TreeHandler(SkyNetNodeInterface node, TreeHandlerDelegator treeHandlerDelegator) { branchingFactor = SkyNetPropertiesReader.getInstance().getIntProperty("SkyNetTreeBranchingFactor"); this.skyNetNode = node; this.treeHandlerDelegator = treeHandlerDelegator; this.treeHandlerDelegator.setSkyNetNode(skyNetNode); this.treeHandlerDelegator.setOwnOverlayNode(skyNetNode.getOverlayNode()); isRoot = false; parentCoordinator = new SkyNetNodeInfoImpl(null, null, null, -1); coordinatorKey = null; level = 0; } /** * This method puts <code>TreeHandler</code> back in its initial state, if the host got off-line * or if the peer left the underlying overlay. */ public void reset() { isRoot = false; } /** * This method tests, if a SkyNet-node is currently the root of the SkyNet-tree. * * @return <code>true</code>, if the node is the root, <code>false</code> otherwise */ public boolean isRoot() { return isRoot; } public void verticalDispatching() { // for later versions } public void horizontalDispatching() { // for later versions } /** * This method returns the information of the current Parent-Coordinator, which is required to * address the Parent-Coordinator. * * @return the <code>SkyNetNodeInfo</code> of the ParentCoordinator */ public SkyNetNodeInfo getParentCoordinator() { if (parentCoordinator != null) { if (parentCoordinator.isComplete()) { return parentCoordinator.clone(); } else { return null; } } else { return null; } } // ---------------------------------------------------------------------- // methods for traveling down the tree // ---------------------------------------------------------------------- private void checkResponsibility( SkyNetID ownID, SkyNetID skyNetCoKey, BigDecimal left, BigDecimal right, int iter) { skyNetNode.getSkyNetNodeInfo().setCoordinatorKey(skyNetCoKey); log.info( " The client " + skyNetNode.getSkyNetNodeInfo().toString() + " is responsible for the CoordinatorKey " + skyNetCoKey.getPlainSkyNetID() + " in the interval[" + left.toPlainString() + ";" + right.toPlainString() + "] @ level " + iter); ISkyNetMonitor monitor = (ISkyNetMonitor) Simulator.getMonitor(); ChurnStatisticsAnalyzer csAnalyzer = (ChurnStatisticsAnalyzer) monitor.getConnectivityAnalyzer(ChurnStatisticsAnalyzer.class); if (iter > 0) { // complete the parentSkyNetNode Info if (isRoot) { log.warn(SkyNetUtilities.getTimeAndNetID(skyNetNode) + "lost the root-position"); csAnalyzer.lostRootPosition(skyNetNode); skyNetNode.getMetricUpdateStrategy().setLastMetricSync(0); } skyNetNode.getSkyNetNodeInfo().setLevel(iter); isRoot = false; lookupParentCoordinator(); } else { if (!isRoot) { log.warn(SkyNetUtilities.getTimeAndNetID(skyNetNode) + "got the root-position"); csAnalyzer.gotRootPosition(skyNetNode); skyNetNode.getMetricUpdateStrategy().setLastMetricSync(0); } skyNetNode.getSkyNetNodeInfo().setLevel(iter); // Also set the observed level at this point skyNetNode.getSkyNetNodeInfo().setObservedLevelFromRoot(0); isRoot = true; skyNetNode.getAttributeUpdateStrategy().resetOnlyAttributeUpdateStrategy(); skyNetNode.getMetricUpdateStrategy().sendNextDataUpdate(); } } private void calculateNextLevel( SkyNetID ownID, SkyNetID skyNetCoKey, BigDecimal left, BigDecimal right, int iter) { if (iter == 0) { coordinatorKey = skyNetCoKey; level = iter; } else { coordinatorKey = skyNetCoKey; level = iter; } if (iter < 100) { // call processNextLevel(...), but before split the interval // defined by left and right in k subintervals as defined by // branchingFactor. BigDecimal interval = right.subtract(left); BigDecimal intervalStep = interval.divide(new BigDecimal(String.valueOf(branchingFactor))); BigDecimal tempLeft = left; BigDecimal tempRight = left.add(new BigDecimal(String.valueOf(intervalStep))); log.info( SkyNetUtilities.getTimeAndNetID(skyNetNode) + "is actually in the interval between " + left.toPlainString() + " and " + right.toPlainString() + ". The size of the interval is" + interval); int correctnessCounter = 0; while (ownID.getID().compareTo(tempRight) > -1) { tempLeft = tempRight; tempRight = tempRight.add(new BigDecimal(String.valueOf(intervalStep))); if (correctnessCounter < branchingFactor) { correctnessCounter++; } else { log.fatal( "There are actually " + (correctnessCounter + 1) + " intervals instead of " + branchingFactor); } } processNextLevel(ownID, tempLeft, tempRight, iter + 1); } else { skyNetNode.getMetricUpdateStrategy().scheduleNextUpdateEvent(); parentCoordinator = null; if (isRoot) { log.warn(SkyNetUtilities.getTimeAndNetID(skyNetNode) + "lost the root-position"); } isRoot = false; log.error( SkyNetUtilities.getTimeAndNetID(skyNetNode) + "is to deep in the tree." + "Probably no predecessor in the overlay can be found" + " to calculate the 'isRootOf'-method"); } } // ---------------------------------------------------------------------- // methods for checking the responsibility-interval on different overlays // ---------------------------------------------------------------------- /** * If it is possible to calculate the responsibility interval of a peer on the current overlay, * this method calculates the corresponding responsibility interval of the node in the ID-space of * SkyNet. In this context, the responsibility interval is used to test, if a SkyNet-node is * responsible for a Coordinator. * * @param id contains the ID of this SkyNet-node */ public void calculateResponsibilityInterval(SkyNetID id) { if (((AbstractOverlayNode<?, ?>) skyNetNode.getOverlayNode()) .getPeerStatus() .equals(PeerStatus.PRESENT)) { // execute getPredecessor-method final SkyNetID ownID = id; treeHandlerDelegator.calculateResponsibilityInterval( ownID, new OperationCallback<OverlayContact<OverlayID<?>>>() { @Override public void calledOperationFailed(Operation<OverlayContact<OverlayID<?>>> op) { calculateResponsibilityIntervalOperationFailed(op); } @Override public void calledOperationSucceeded(Operation<OverlayContact<OverlayID<?>>> op) { calculateResponsibilityIntervalOperationSucceeded(op, ownID); } }); } else { log.warn("SkyNetNode cannot get Predecessor" + ", because he is not PRESENT"); } } void calculateResponsibilityIntervalOperationFailed(Operation<OverlayContact<OverlayID<?>>> op) { treeHandlerDelegator.calculateResponsibilityIntervalOperationFailed(op); skyNetNode.getMetricUpdateStrategy().scheduleNextUpdateEvent(); } void calculateResponsibilityIntervalOperationSucceeded( Operation<OverlayContact<OverlayID<?>>> op, SkyNetID ownID) { treeHandlerDelegator.calculateResponsibilityIntervalOperationSucceeded(op); int iter = 0; BigDecimal left = new BigDecimal(0); BigDecimal right = new BigDecimal(1); level = 0; processNextLevel(ownID, left, right, iter); } // ---------------------------------------------------------------------- // methods for traveling down the tree // ---------------------------------------------------------------------- /** * This method is responsible for the calculation of the position of the SkyNet-node in the * SkyNet-tree. Additionally, it determines the key of the Parent-Coordinator, which can be looked * up.<br> * This method starts the recursive calculation, where first the determination of the Coordinator * for every new interval is executed. Then it is checked, if the SkyNet-node is responsible for * that Coordinator. In case of a positive outcome, the Parent-Coordinator is looked up, * otherwise, the interval at the next level is calculated, to which the SkyNet-node must descend. * * @param ownID the ID of this SkyNet-node * @param left the left bound of the interval * @param right the right bound of the interval * @param iter the current level */ private void processNextLevel(SkyNetID ownID, BigDecimal left, BigDecimal right, int iter) { BigDecimal temp = left.add(right); temp = temp.divide(new BigDecimal(String.valueOf(2))); // BigDecimal temp = new BigDecimal((left + right) / 2); SkyNetID skyNetCoKey = new SkyNetID(temp); // call the process-method for the corresponding overlay treeHandlerDelegator.processNextLevel( ownID, skyNetCoKey, left, right, iter, new OperationCallback<Object>() { @Override public void calledOperationFailed(Operation<Object> op) { processNextLevelOperationFailed(op); } @Override public void calledOperationSucceeded(Operation<Object> op) { processNextLevelOperationSucceeded(op); } }); } void processNextLevelOperationFailed(Operation<?> op) { treeHandlerDelegator.processNextLevelOperationFailed(op); skyNetNode.getMetricUpdateStrategy().scheduleNextUpdateEvent(); } void processNextLevelOperationSucceeded(Operation<?> op) { ProcessNextLevelResult result = treeHandlerDelegator.processNextLevelOperationSucceeded(op); if (result.isKeyResponsibility()) { checkResponsibility( result.getOwnID(), result.getSkyNetCoKey(), result.getLeft(), result.getRight(), result.getIter()); } else { calculateNextLevel( result.getOwnID(), result.getSkyNetCoKey(), result.getLeft(), result.getRight(), result.getIter()); } } // ---------------------------------------------------------------------- // methods for looking up the needed additional information of the // ParentCoordinator on different overlays // ---------------------------------------------------------------------- private void lookupParentCoordinator() { if (((AbstractOverlayNode<?, ?>) skyNetNode.getOverlayNode()) .getPeerStatus() .equals(PeerStatus.PRESENT)) { log.debug( SkyNetUtilities.getTimeAndNetID(skyNetNode) + "starts a lookup for the key " + coordinatorKey.getPlainSkyNetID()); treeHandlerDelegator.lookupParentCoordinator( coordinatorKey, new OperationCallback<OverlayContact<OverlayID<?>>>() { @Override public void calledOperationFailed(Operation<OverlayContact<OverlayID<?>>> op) { lookupOperationFailed(op); } @Override public void calledOperationSucceeded(Operation<OverlayContact<OverlayID<?>>> op) { lookupOperationSucceeded(op); } }); } else { log.warn("SkyNetNode cannot lookup ParentCoordinator" + ", because he is not PRESENT"); } } void lookupOperationFailed(Operation<OverlayContact<OverlayID<?>>> op) { treeHandlerDelegator.lookupOperationFailed(op); skyNetNode.getMetricUpdateStrategy().scheduleNextUpdateEvent(); } void lookupOperationSucceeded(Operation<OverlayContact<OverlayID<?>>> op) { LookupResult result = treeHandlerDelegator.lookupOperationSucceeded(op); parentCoordinator = new SkyNetNodeInfoImpl( result.getSkyNetID(), coordinatorKey, DefaultTransInfo.getTransInfo( result.getContact().getTransInfo().getNetId(), skyNetNode.getPort()), level); log.info( parentCoordinator.toString() + " is parentCoordinator of " + skyNetNode.getSkyNetNodeInfo().toString()); skyNetNode.getMetricUpdateStrategy().sendNextDataUpdate(); } }