private void initState() { int numNodes = state.getNodeMap().size(); int numSlots = numNodes * slotsPerNode; this.legend = new Legend(null, null, 0); int latSides = (int) Math.ceil(Math.pow(numNodes, 1 / 3.0)); log.info("Lattice of " + numNodes + " requires " + latSides + " per side"); this.lattice = new Lattice<Lattice<Void>>(latSides); List<String> nodeNames = new ArrayList<String>(); List<Lattice<Void>> nodeLatti = new ArrayList<Lattice<Void>>(); for (GridNode node : state.getNodeMap().values()) { Lattice<Void> nodeLattice = new Lattice<Void>(nodeLatSides); List<String> slotNames = new ArrayList<String>(); List<Void> slots = new ArrayList<Void>(); for (int i = 0; i < slotsPerNode; i++) { slotNames.add("" + i); slots.add(null); } nodeLattice.addItems(slotNames, slots); nodeNames.add(node.getShortName()); nodeLatti.add(nodeLattice); // log.warn("Adding lattice for node "+node.getShortName()); } lattice.addItems(nodeNames, nodeLatti); // Initialize actors from the grid state for (GridNode node : state.getNodeMap().values()) { int s = 0; for (GridJob job : node.getSlots()) { if (job == null) continue; String slotName = s + ""; JobActor jobActor = createJobActor(job); jobActor.pos = getLatticePos(node.getShortName(), slotName); log.info( "Starting job {} on slot: {}", job.getFullJobId(), node.getShortName() + "#" + slotName); addJobActor(job.getFullJobId(), jobActor); s++; } } }
private void applyStart(GridJob job) { String fullJobId = job.getFullJobId(); Collection<JobActor> actors = jobActorMap.get(fullJobId); if (actors.isEmpty()) { JobActor jobActor = createJobActor(job); addJobActor(fullJobId, jobActor); actors = jobActorMap.get(fullJobId); } if (job.getNode() == null) { log.warn("No node for job being started: {}", fullJobId); return; } log.debug("Starting job {} on {}", fullJobId, job.getNode().getShortName()); String nodeName = job.getNode().getShortName(); if (actors.size() > 1) { log.warn("More than one actor for job being started: " + fullJobId); } JobActor jobActor = actors.iterator().next(); int i = 0; GridJob[] nodeJobs = job.getNode().getSlots(); for (int s = 0; s < nodeJobs.length; s++) { GridJob nodeJob = nodeJobs[s]; if (nodeJob == null) continue; if (!nodeJob.getFullJobId().equals(fullJobId)) continue; if (i > 0) { jobActor = cloneJobActor(fullJobId); } PVector endPos = getLatticePos(nodeName, s + ""); // TODO: random outside location in direction of vector from 0,0,0 PVector startPos = new PVector(1000, 1000, 1000); jobActor.pos = startPos; if (tweenChanges) { // scale duration to the distance that needs to be traveled float distance = jobActor.pos.dist(endPos); float duration = (DURATION_JOB_START * distance / DISTANCE_JOB_START) * 0.6f; Tween tween = new Tween("start_job_" + fullJobId + "#" + i, getTweenDuration(duration)) .addPVector(jobActor.pos, endPos) .call(jobActor, "jobStarted") .setEasing(Tween.SINE_OUT) .noAutoUpdate(); jobActor.tweens.add(tween); } else { jobActor.pos.set(endPos); } i++; } }
private void applyEnd(GridJob job, long endOffset) { String fullJobId = job.getFullJobId(); Collection<JobActor> actors = jobActorMap.get(fullJobId); if (actors == null || actors.isEmpty()) { log.warn("Cannot end job that does not exist: {}", fullJobId); return; } log.debug("Finishing job {} on node {}", fullJobId, job.getNode().getShortName()); int i = 0; for (JobActor jobActor : actors) { PVector endPos = jobActor.getPos().get(); endPos.mult(10.0f); if (tweenChanges) { // scale duration to the distance that needs to be traveled float distance = jobActor.pos.dist(endPos); float duration = (DURATION_JOB_END * distance / DURATION_JOB_END) * 0.6f; Tween tween = new Tween("end_job_" + fullJobId + "#" + i, getTweenDuration(duration)) .addPVector(jobActor.pos, endPos) .call(jobActor, "jobEnded") .setEasing(Tween.SINE_IN) .noAutoUpdate(); jobActor.tweens.add(tween); } else { jobActor.jobEnded(); } i++; } }
@Override public void run() { while (true) { switch (playState) { case BUFFERING: bufferToNextPosition(); break; case PLAYING: Date currDate = new Date(); long elapsed = (int) ((currDate.getTime() - lastSliceRequestDate.getTime()) * playSpeed); this.lastSliceRequestDate = currDate; // Check if we've been truncated, and move forward if necessary if (totalElapsed < timeline.getFirstOffset()) { log.info( "Elapsed time ({}) occurs before the current timeline ({})", totalElapsed, timeline.getFirstOffset()); long position = elapsed; boolean noMatch = true; while (noMatch) { if (position != timeline.getFirstOffset()) { position = timeline.getFirstOffset(); try { Thread.sleep(500); } catch (InterruptedException e) { // Ignore } } else { noMatch = false; } } log.info("Will buffer to new position: {}", position); bufferAtPosition(position); break; } // Update actors and build a usage map Map<String, Integer> slotsUsedByUser = new HashMap<String, Integer>(); Iterator<? extends Actor> i = getJobActors().values().iterator(); while (i.hasNext()) { Actor actor = i.next(); if (actor instanceof JobActor) { JobActor jobActor = (JobActor) actor; if (jobActor.defunct) { removeJobActor(jobActor.name, jobActor); } else { int slots = 1; if (jobActor.queued) { // If a job is queued then it is represented by a single sprite, so we need the // actual number of slots GridJob job = state.getJobByFullId(jobActor.name); if (job != null) { slots = job.getSlots(); } } if (jobActor.getName().contains(":")) { // Parse a jobId like this: 1275988.2828-4000:1 try { Pattern p = Pattern.compile("(\\d+)\\.(\\d+)-(\\d+):(\\d+)"); Matcher m = p.matcher(jobActor.getName()); if (m.matches()) { int start = Integer.parseInt(m.group(2)); int end = Integer.parseInt(m.group(3)); int interval = Integer.parseInt(m.group(4)); slots = (end - start) / interval; } } catch (Exception e) { log.error("Error parsing jobId: " + jobActor.getName(), e); } } else if (jobActor.getName().contains(",")) { // Parse a jobId like this: 2968157.205,211 try { Pattern p = Pattern.compile("(\\d+)\\.(\\d+),(\\d+)"); Matcher m = p.matcher(jobActor.getName()); if (m.matches()) { int first = Integer.parseInt(m.group(2)); int second = Integer.parseInt(m.group(3)); // There are two jobs listed here, so we require twice the number of slots slots *= 2; } } catch (Exception e) { log.error("Error parsing jobId: " + jobActor.getName(), e); } } String user = jobActor.getUsername(); if (!slotsUsedByUser.containsKey(user)) { slotsUsedByUser.put(user, 0); } if (!jobActor.queued) { slotsUsedByUser.put(user, slotsUsedByUser.get(user) + slots); } } } } legend.retain(slotsUsedByUser); updateState(elapsed); break; case READY: break; case PAUSED: break; case END: return; default: log.error("Invalid play state: " + playState); break; } try { Thread.sleep(50); } catch (InterruptedException e) { // Ignore } } }
private JobActor createJobActor(GridJob job) { JobActor jobActor = new JobActor(null, job.getOwner()); jobActor.color = legend.getItemColor(job.getOwner()); jobActor.name = job.getFullJobId(); return jobActor; }