package io.hummer.prefetch.sim; import io.hummer.prefetch.PrefetchingService.ServiceInvocation; import io.hummer.prefetch.TestConstants; import io.hummer.prefetch.context.Context; import io.hummer.prefetch.context.ContextPredictor; import io.hummer.prefetch.context.Location; import io.hummer.prefetch.context.NetworkQuality; import io.hummer.prefetch.context.Time; import io.hummer.prefetch.context.Path.PathPoint; import io.hummer.prefetch.impl.InvocationPredictor; import io.hummer.prefetch.impl.UsagePattern; import io.hummer.prefetch.sim.VehicleSimulation.MovingEntities; import io.hummer.prefetch.sim.VehicleSimulation.MovingEntity; import io.hummer.prefetch.sim.swisscom.CellularCoverage; import io.hummer.prefetch.sim.util.Util; import io.hummer.prefetch.sim.ws.VehicleInfoService; import io.hummer.prefetch.sim.ws.VehicleInfoService.VehicleInfoServiceImpl; import io.hummer.prefetch.ws.W3CEndpointReferenceUtils; import io.hummer.prefetch.ws.WSClient; import io.hummer.util.log.LogUtil; import io.hummer.util.xml.XMLUtil; import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.xml.ws.Endpoint; import javax.xml.ws.wsaddressing.W3CEndpointReference; import org.apache.log4j.Logger; import org.w3c.dom.Element; public class SimulationTestData { public static final String TRACE_FILE = System.getProperty("user.home") + "/Desktop/traces.txt"; private static Map<String, List<String>> file = new HashMap<>(); private static XMLUtil xmlUtil = new XMLUtil(); private static final Logger LOG = LogUtil.getLogger(); public static class ServiceUsage { public UsagePattern pattern; public InvocationPredictor invocationPredictor; public static UsagePattern combine(final ServiceUsage ... usages) { UsagePattern[] patterns = new UsagePattern[usages.length]; for(int i = 0; i < usages.length; i ++) patterns[i] = usages[i].pattern; return UsagePattern.combine(patterns); } } public static MovingEntity getData(String id) { List<String> lines = getLines(id); MovingEntity result = new MovingEntity(); result.id = id; for (String s : lines) { String[] parts = s.split("setdest"); if (parts.length > 1) { String[] coords = parts[1].trim().split(" "); String time = parts[0].trim().split(" ")[2]; boolean loadDetails = false; result.addPathPoint(Double.parseDouble(time), Double.parseDouble(coords[0]), Double.parseDouble(coords[1]), Double.parseDouble(coords[2].replace("\"", "")), loadDetails); } } return result; } private static List<String> getLines(String id) { if (file.isEmpty()) { String regex = ".*\\$node_\\(([A-Za-z0-9]+)\\).*"; List<String> lines = Util.readFile(TRACE_FILE); for (String s : lines) { if (s.matches(regex)) { String i = s.replaceAll(regex, "$1"); if (!file.containsKey(i)) { file.put(i, new LinkedList<String>()); } file.get(i).add(s); } } } List<String> lines = file.get(id); if (lines != null) return lines; return Collections.emptyList(); } static void setTunnelOverrides() { //46.58232725478691,8.56863682841651 NetworkQuality q1 = new NetworkQuality(false); /* Gotthard Tunnel: */ CellularCoverage.OVERRIDES.put( new Location(46.58232725478691,8.56863682841651), q1); CellularCoverage.OVERRIDES.put( new Location(46.61630210986323,8.578053356802688), q1); CellularCoverage.OVERRIDES.put( new Location(46.62514880956553,8.580507305472487), q1); CellularCoverage.OVERRIDES.put( new Location(46.63688960569387,8.58376530161051), q1); CellularCoverage.OVERRIDES.put( new Location(46.649437172968,8.587248769273087), q1); CellularCoverage.OVERRIDES.put( new Location(46.65707885240678,8.58937106896852), q1); CellularCoverage.OVERRIDES.put( new Location(46.5434865755487,8.596293438544723), q1); CellularCoverage.OVERRIDES.put( new Location(46.53798057183448,8.600210400527107), q1); CellularCoverage.OVERRIDES.put( new Location(46.53485189855097,8.602435735412291), q1); } public static MovingEntities getData(int fromCar, int toCar) { setTunnelOverrides(); String file = Constants.TMP_DIR + "/traces.xml.gz"; MovingEntities result = new MovingEntities(); if(new File(file).exists()) { String content = Util.loadStringFromGzip(file); try { result = xmlUtil.toJaxbObject(MovingEntities.class, xmlUtil.toElement(content)); } catch (Exception e) { throw new RuntimeException(e); } } long t1, t2; double timeBetweenPointsTotal = 0; double totalNumPoints = 0; for (int i = fromCar; i <= toCar; i++) { String id = "" + i; if(!result.containsID(id)) { System.out.println("Retrieving data for car " + id); t1 = System.currentTimeMillis(); MovingEntity ent = getData(id); result.entities.add(ent); t2 = System.currentTimeMillis(); LOG.info("adding entity " + i + ": " + ent.path.size() + " points - " + Math.abs(t2 - t1) + "ms"); ent.getNetworkOutages(); try { String xml = xmlUtil.toString(result); Util.storeStringGzipped(file, xml); } catch (Exception e) { throw new RuntimeException(e); } } MovingEntity ent = result.getEntity(id); /* assert that path order is correct */ PathPoint ptNoNetFirst = null; PathPoint ptNoNetLast = null; double maxDistance = 60*10; for(int j = 0; j < ent.path.size(); j ++) { PathPoint p1 = ent.path.points.get(j); CellularCoverage.setOverrideIfExists(p1); // if(p1.cellNetworkCoverage._2g_gsm && !p1.cellNetworkCoverage._3g_hspa && ! // p1.cellNetworkCoverage._3g_umts && !p1.cellNetworkCoverage._4g_lte) // System.out.println("ONLY 2G!!"); if(j < ent.path.size() - 1) { PathPoint p2 = ent.path.points.get(j + 1); double timeBetweenPoints = p2.time.time - p1.time.time; timeBetweenPointsTotal += timeBetweenPoints; if(p1.time.time > p2.time.time) { throw new RuntimeException("non-chronological path order"); } /* if the distance between two points is too big, end the path here. */ if(timeBetweenPoints > maxDistance) { LOG.info("Cutting path of vehicle " + id + " at time " + p1.time + ", distance: " + timeBetweenPoints); ent.path.points = ent.path.points.subList(0, j + 1); } } /* check for connectivity */ if(!p1.cellNetworkCoverage.hasSufficientCoverage()) { if(j <= 1) { /* the first point (and one before that) should always * have connectivity (for simulation purposes) */ NetworkQuality goodNetworkCoverage = new NetworkQuality(true); if(j == 0) { p1.cellNetworkCoverage = goodNetworkCoverage; LOG.info("Setting net coverage to true: " + p1.time + " - " + p1.coordinates); } else if(j == 1) { PathPoint pNew = new PathPoint(p1.time.add(-10.0), p1.coordinates, goodNetworkCoverage); ent.path.points.add(0, pNew); j ++; } } if(ptNoNetFirst == null) { if(j > 0) { LOG.debug(ent.path.points.get(j - 1).coordinates + ": " + CellularCoverage.getCoverage(46.552472293321905,8.589899093722023)); } ptNoNetFirst = p1; } ptNoNetLast = p1; } if(p1.cellNetworkCoverage.hasSufficientCoverage() || j >= ent.path.size() - 1){ if(ptNoNetLast != null) { double time = ptNoNetLast.time.time - ptNoNetFirst.time.time; LOG.info("Car " + id + ": net down for " + time + "secs at " + ptNoNetFirst.time.time + ": " + ptNoNetFirst.coordinates + " to " + ptNoNetLast.coordinates); if(time > maxDistance) { int index = ent.path.points.indexOf(ptNoNetFirst); LOG.info("Offline for too long. Cutting path of vehicle " + id + " at time " + ptNoNetFirst.time + ", index " + index); ent.path.points = ent.path.points.subList(0, index); break; } //LOG.debug(ent.path.points.get(j + 1).coordinates); } ptNoNetFirst = null; ptNoNetLast = null; } } if(fromCar == toCar) { // TODO System.out.println(ent.path.points); } totalNumPoints += ent.path.size(); } /* trim to number of cars */ for(MovingEntity ent : new LinkedList<>(result.entities)) { if(Double.parseDouble(ent.id) < fromCar || Double.parseDouble(ent.id) > toCar) result.entities.remove(ent); } //System.out.println(result.entities.get(0).path); LOG.info("Average time between time points: " + (timeBetweenPointsTotal / totalNumPoints)); return result; } static ServiceUsage getServiceUsage1() throws Exception { String template = "<tns:getVicinityInfo " + "xmlns:tns=\"" + VehicleInfoService.NAMESPACE + "\">" + "<lat>{{" + Context.ATTR_LOCATION_LAT + "}}</lat>" + "<lon>{{" + Context.ATTR_LOCATION_LON + "}}</lon>" + "</tns:getVicinityInfo>"; //UsagePattern usagePattern = UsagePattern.periodic(60, 100, 10); ContextPredictor<Object> ctxPredict = new ContextPredictor.DefaultPredictor(); return constructServiceUsage(template, false, ctxPredict, 100); } static ServiceUsage getServiceUsage2() throws Exception { String template = "<tns:getTrafficInfo " + "xmlns:tns=\"" + VehicleInfoService.NAMESPACE + "\">" + "<lat>{{" + Context.ATTR_LOCATION_LAT + "}}</lat>" + "<lon>{{" + Context.ATTR_LOCATION_LON + "}}</lon>" + "</tns:getTrafficInfo>"; final double updateSeconds = 60; double timeInterval = 10; ContextPredictor<Object> ctxPredict = new ContextPredictor. DefaultPredictorWithUpdateInterval(updateSeconds, timeInterval); return constructServiceUsage(template, false, ctxPredict, 50); } static ServiceUsage getServiceUsage3() throws Exception { String template = "<tns:streamMedia " + "xmlns:tns=\"" + VehicleInfoService.NAMESPACE + "\">" + "<mediaID>{{" + TestConstants.ATTR_MEDIA_ID + "}}</mediaID>" + "<chunkID>{{" + TestConstants.ATTR_MEDIA_NEXT_CHUNK + "}}</chunkID>" + "</tns:streamMedia>"; final double updateSeconds = 20; final double songLength = 180; double timeInterval = 10; ContextPredictor<Object> ctxPredict = new ContextPredictor. DefaultPredictorWithUpdateInterval(updateSeconds, timeInterval) { public Context<Object> predict(Context<Object> currentContext, Time t) { Context<Object> context = super.predict(currentContext, t); context.setContextAttribute(TestConstants.ATTR_MEDIA_ID, "song" + (int)(t.time / songLength)); context.setContextAttribute(TestConstants.ATTR_MEDIA_NEXT_CHUNK, "chunk" + (int)(((double)(t.time % songLength))/updateSeconds)); return context; } }; return constructServiceUsage(template, true, ctxPredict, 150); } static ServiceUsage getServiceUsage4() throws Exception { String template = "<tns:reroute " + "xmlns:tns=\"" + VehicleInfoService.NAMESPACE + "\">" + "<lat>{{" + Context.ATTR_LOCATION_LAT + "}}</lat>" + "<lon>{{" + Context.ATTR_LOCATION_LON + "}}</lon>" + "</tns:reroute>"; final double updateSeconds = 300; double timeInterval = 10; ContextPredictor<Object> ctxPredict = new ContextPredictor. DefaultPredictorWithUpdateInterval(updateSeconds, timeInterval); return constructServiceUsage(template, false, ctxPredict, 75); } static ServiceUsage getServiceUsage5() throws Exception { String template = "<tns:getMail " + "xmlns:tns=\"" + VehicleInfoService.NAMESPACE + "\">" + "</tns:getMail>"; final double updateSeconds = 180; double timeInterval = 10; ContextPredictor<Object> ctxPredict = new ContextPredictor. DefaultPredictorWithUpdateInterval(updateSeconds, timeInterval); return constructServiceUsage(template, false, ctxPredict, 50); } static ServiceUsage getServiceUsage6() throws Exception { String template = "<tns:syncUpdates " + "xmlns:tns=\"" + VehicleInfoService.NAMESPACE + "\">" + "</tns:syncUpdates>"; final double updateSeconds = 600; double timeInterval = 10; ContextPredictor<Object> ctxPredict = new ContextPredictor. DefaultPredictorWithUpdateInterval(updateSeconds, timeInterval); return constructServiceUsage(template, false, ctxPredict, 100); } static ServiceUsage constructServiceUsage(String template, boolean prefetchPossible, //UsagePattern usagePattern, ContextPredictor<Object> ctxPredictor, double invocationKbps) { try { Element body = WSClient.toElement(template); ServiceInvocation tmp = new ServiceInvocation(); tmp.serviceCall = WSClient.createEnvelopeFromBody(body); // tmp.prefetchPossible = prefetchPossible; tmp.serviceEPR = eprTrafficService; double stepSize = 10; InvocationPredictor invPred = new InvocationPredictor. TemplateBasedInvocationPredictor(xmlUtil.toString(tmp), ctxPredictor, stepSize); UsagePattern usagePattern = UsagePattern.predictionBased(invPred, null, invocationKbps); // ServiceInvocationBuilder b = new ServiceInvocationBuilder. // TemplateBasedInvocationBuilder(xmlUtil.toString(tmp)); // b.prefetchPossible = tmp.prefetchPossible; // b.serviceEPR = tmp.serviceEPR; ServiceUsage use = new ServiceUsage(); // use.invocation = b; use.pattern = usagePattern; use.invocationPredictor = invPred; return use; } catch (Exception e) { throw new RuntimeException(e); } } private static String urlTrafficService; private static W3CEndpointReference eprTrafficService; public static void setServiceURL(String serviceURL) { urlTrafficService = serviceURL; eprTrafficService = W3CEndpointReferenceUtils. createEndpointReference(urlTrafficService); } static void deployTestServices(String url) throws Exception { setServiceURL(url); VehicleInfoService s = new VehicleInfoServiceImpl(); Endpoint.publish(urlTrafficService, s); WSClient.cachedResponseObject = WSClient.createEnvelopeFromBody( new XMLUtil().toElement("<result/>")); } }