diff options
Diffstat (limited to 'opendc-compute/opendc-compute-simulator/src/main/java/org/opendc')
3 files changed, 281 insertions, 311 deletions
diff --git a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java index f1e747b3..f357b164 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java +++ b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java @@ -38,7 +38,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.opendc.common.Dispatcher; import org.opendc.common.util.Pacer; -import org.opendc.compute.api.Flavor; import org.opendc.compute.api.TaskState; import org.opendc.compute.simulator.host.HostListener; import org.opendc.compute.simulator.host.HostModel; @@ -123,13 +122,6 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { private final List<Integer> terminatedTasks = new ArrayList<>(); /** - * The registered flavors for this compute service. - */ - private final Map<Integer, ServiceFlavor> flavorById = new HashMap<>(); - - private final List<ServiceFlavor> flavors = new ArrayList<>(); - - /** * The registered tasks for this compute service. */ private final Map<Integer, ServiceTask> taskById = new HashMap<>(); @@ -176,20 +168,19 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { || newState == TaskState.PAUSED || newState == TaskState.TERMINATED || newState == TaskState.FAILED) { - LOGGER.info("task {} {} {} finished", task.getId(), task.getName(), task.getFlavor()); + LOGGER.info("task {} {} {} finished", task.getId(), task.getName()); if (activeTasks.remove(task) != null) { tasksActive--; } HostView hv = hostToView.get(host); - final ServiceFlavor flavor = task.getFlavor(); if (hv != null) { - hv.provisionedCpuCores -= flavor.getCpuCoreCount(); - hv.availableCpuCores += flavor.getCpuCoreCount(); + hv.provisionedCpuCores -= task.getCpuCoreCount(); + hv.availableCpuCores += task.getCpuCoreCount(); hv.instanceCount--; - hv.availableMemory += flavor.getMemorySize(); - hv.provisionedGpuCores -= flavor.getGpuCoreCount(); + hv.availableMemory += task.getMemorySize(); + hv.provisionedGpuCores -= task.getGpuCoreCount(); } else { LOGGER.error("Unknown host {}", host); } @@ -436,10 +427,8 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { long now = clock.millis(); SchedulingRequest request = new SchedulingRequest(task, now); - ServiceFlavor flavor = task.getFlavor(); - // If the task has parents, put in blocked tasks - if (!flavor.getParents().isEmpty()) { + if (task.hasParents()) { blockedTasks.put(task.getId(), request); return null; } @@ -457,17 +446,21 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { void addCompletedTask(ServiceTask completedTask) { int parentId = completedTask.getId(); - for (int taskId : completedTask.getFlavor().getChildren()) { - SchedulingRequest request = blockedTasks.get(taskId); - if (request != null) { - request.getTask().getFlavor().removeFromParents(parentId); + if (!completedTask.hasChildren()) { + return; + } - Set<Integer> pendingDependencies = request.getTask().getFlavor().getParents(); + for (int childTaskId : completedTask.getChildren()) { + SchedulingRequest childRequest = blockedTasks.get(childTaskId); + if (childRequest != null) { + ServiceTask childTask = childRequest.getTask(); + childTask.removeFromParents(parentId); - if (pendingDependencies.isEmpty()) { - taskQueue.add(request); + // If the child task has no more parents, it can be scheduled + if (!childTask.hasParents()) { + taskQueue.add(childRequest); tasksPending++; - blockedTasks.remove(taskId); + blockedTasks.remove(childTaskId); } } } @@ -475,8 +468,8 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { void addTerminatedTask(ServiceTask task) { - for (int taskId : task.getFlavor().getChildren()) { - SchedulingRequest request = blockedTasks.get(taskId); + for (int childTaskId : task.getChildren()) { + SchedulingRequest request = blockedTasks.get(childTaskId); if (request != null) { ServiceTask childTask = request.getTask(); @@ -491,11 +484,6 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { } } - void delete(ServiceFlavor flavor) { - flavorById.remove(flavor.getTaskId()); - flavors.remove(flavor); - } - void delete(ServiceTask task) { completedTasks.remove(task); taskById.remove(task.getId()); @@ -537,12 +525,10 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { final SchedulingRequest req = result.getReq(); final ServiceTask task = req.getTask(); - final ServiceFlavor flavor = task.getFlavor(); - if (result.getResultType() == SchedulingResultType.FAILURE) { LOGGER.trace("Task {} selected for scheduling but no capacity available for it at the moment", task); - if (flavor.getMemorySize() > maxMemory || flavor.getCpuCoreCount() > maxCores) { + if (task.getMemorySize() > maxMemory || task.getCpuCoreCount() > maxCores) { // Remove the incoming image taskQueue.remove(req); tasksPending--; @@ -571,7 +557,7 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { try { task.setHost(host); - task.scheduledAt = clock.instant(); + task.setScheduledAt(clock.millis()); host.spawn(task); @@ -579,10 +565,10 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { attemptsSuccess++; hv.instanceCount++; - hv.provisionedCpuCores += flavor.getCpuCoreCount(); - hv.availableCpuCores -= flavor.getCpuCoreCount(); - hv.availableMemory -= flavor.getMemorySize(); - hv.provisionedGpuCores += flavor.getGpuCoreCount(); + hv.provisionedCpuCores += task.getCpuCoreCount(); + hv.availableCpuCores -= task.getCpuCoreCount(); + hv.availableMemory -= task.getMemorySize(); + hv.provisionedGpuCores += task.getGpuCoreCount(); activeTasks.put(task, host); @@ -651,44 +637,15 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { } @NotNull - public List<Flavor> queryFlavors() { - checkOpen(); - return new ArrayList<>(service.flavors); - } + public ServiceTask newTask(ServiceTask task) { - @NotNull - public ServiceFlavor newFlavor( - int taskId, - int cpuCount, - long memorySize, - int gpuCoreCount, - @NotNull Set<Integer> parents, - @NotNull Set<Integer> children, - @NotNull Map<String, ?> meta) { checkOpen(); final ComputeService service = this.service; - return new ServiceFlavor(service, taskId, cpuCount, memorySize, gpuCoreCount, parents, children, meta); - } + task.setService(service); - @NotNull - public ServiceTask newTask( - int id, - @NotNull String name, - @NotNull TaskNature nature, - @NotNull Duration duration, - @NotNull Long deadline, - @NotNull ServiceFlavor flavor, - @NotNull Workload workload, - @NotNull Map<String, ?> meta) { - checkOpen(); - - final ComputeService service = this.service; - - ServiceTask task = new ServiceTask(service, id, name, nature, duration, deadline, flavor, workload, meta); - - service.taskById.put(id, task); + service.taskById.put(task.getId(), task); service.tasksTotal++; @@ -715,9 +672,6 @@ public final class ComputeService implements AutoCloseable, CarbonReceiver { @Nullable public void rescheduleTask(@NotNull ServiceTask task, @NotNull Workload workload) { ServiceTask internalTask = findTask(task.getId()); - // SimHost from = service.lookupHost(internalTask); - - // from.delete(internalTask); internalTask.setHost(null); diff --git a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceFlavor.java b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceFlavor.java deleted file mode 100644 index 2d6f0342..00000000 --- a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceFlavor.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2022 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.simulator.service; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import org.jetbrains.annotations.NotNull; -import org.opendc.compute.api.Flavor; - -/** - * Implementation of {@link Flavor} provided by {@link ComputeService}. - */ -public final class ServiceFlavor implements Flavor { - private final ComputeService service; - private final int taskId; - private final int cpuCoreCount; - private final long memorySize; - private final int gpuCoreCount; - private final Set<Integer> parents; - private final Set<Integer> children; - private final Map<String, ?> meta; - - ServiceFlavor( - ComputeService service, - int taskId, - int cpuCoreCount, - long memorySize, - int gpuCoreCount, - Set<Integer> parents, - Set<Integer> children, - Map<String, ?> meta) { - this.service = service; - this.taskId = taskId; - this.cpuCoreCount = cpuCoreCount; - this.memorySize = memorySize; - this.gpuCoreCount = gpuCoreCount; - this.parents = parents; - this.children = children; - this.meta = meta; - } - - @Override - public int getCpuCoreCount() { - return cpuCoreCount; - } - - @Override - public long getMemorySize() { - return memorySize; - } - - @Override - public int getGpuCoreCount() { - return gpuCoreCount; - } - - @Override - public int getTaskId() { - return taskId; - } - - @NotNull - @Override - public Map<String, Object> getMeta() { - return Collections.unmodifiableMap(meta); - } - - @Override - public void reload() { - // No-op: this object is the source-of-truth - } - - @Override - public void delete() { - service.delete(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ServiceFlavor flavor = (ServiceFlavor) o; - return service.equals(flavor.service) && taskId == flavor.taskId; - } - - @Override - public int hashCode() { - return Objects.hash(service, taskId); - } - - @Override - public String toString() { - return "Flavor[name=" + taskId + "]"; - } - - public void removeFromParents(List<Integer> completedTasks) { - for (int task : completedTasks) { - this.removeFromParents(task); - } - } - - public void removeFromParents(int completedTask) { - this.parents.remove(completedTask); - } - - public boolean isInDependencies(int task) { - return this.parents.contains(task); - } - - @Override - public @NotNull Set<Integer> getParents() { - return parents; - } - - @Override - public @NotNull Set<Integer> getChildren() { - return children; - } -} diff --git a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceTask.java b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceTask.java index 57bbb7c3..8c066e4f 100644 --- a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceTask.java +++ b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ServiceTask.java @@ -22,15 +22,11 @@ package org.opendc.compute.simulator.service; -import java.time.Duration; -import java.time.Instant; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Objects; +import java.util.Set; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.opendc.compute.api.TaskState; import org.opendc.compute.simulator.TaskWatcher; import org.opendc.compute.simulator.host.SimHost; @@ -45,23 +41,32 @@ import org.slf4j.LoggerFactory; public class ServiceTask { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceTask.class); - private final ComputeService service; + private ComputeService service; private final int id; + private final ArrayList<Integer> parents; + private final Set<Integer> children; private final String name; - private final TaskNature nature; - private final Duration duration; - private final Long deadline; - private ServiceFlavor flavor; + private final boolean deferrable; + + private final long duration; + private long deadline; public Workload workload; - private final Map<String, ?> meta; // TODO: remove this + private final int cpuCoreCount; + private final double cpuCapacity; + private final double totalCPULoad; + private final long memorySize; + + private final int gpuCoreCount; + private final double gpuCapacity; + private final long gpuMemorySize; - private final List<TaskWatcher> watchers = new ArrayList<>(); - private TaskState state = TaskState.CREATED; - Instant scheduledAt = null; - Instant submittedAt; - Instant finishedAt; + private final List<TaskWatcher> watchers = new ArrayList<>(1); + private int stateOrdinal = TaskState.CREATED.ordinal(); + private long submittedAt; + private long scheduledAt; + private long finishedAt; private SimHost host = null; private String hostName = null; @@ -70,115 +75,256 @@ public class ServiceTask { private int numFailures = 0; private int numPauses = 0; - ServiceTask( - ComputeService service, - int id, - String name, - TaskNature nature, - Duration duration, - Long deadline, - ServiceFlavor flavor, - Workload workload, - Map<String, ?> meta) { - this.service = service; - this.id = id; - this.name = name; - this.nature = nature; - this.duration = duration; - this.deadline = deadline; - this.flavor = flavor; - this.workload = workload; - this.meta = meta; + /// ////////////////////////////////////////////////////////////////////////////////////////////////// + /// Getters and Setters + /// ////////////////////////////////////////////////////////////////////////////////////////////////// - this.submittedAt = this.service.getClock().instant(); + public ComputeService getService() { + return service; + } + + public void setService(ComputeService service) { + this.service = service; } public int getId() { return id; } - @NotNull - public TaskNature getNature() { - return nature; + public ArrayList<Integer> getParents() { + return parents; } - @NotNull - public Duration getDuration() { + public Set<Integer> getChildren() { + return children; + } + + public String getName() { + return name; + } + + public boolean getDeferrable() { + return deferrable; + } + + public long getDuration() { return duration; } - @NotNull - public Long getDeadline() { + public long getDeadline() { return deadline; } - @NotNull - public String getName() { - return name; + public void setDeadline(long deadline) { + this.deadline = deadline; } - @NotNull - public ServiceFlavor getFlavor() { - return flavor; + public Workload getWorkload() { + return workload; } - @NotNull - public Map<String, Object> getMeta() { - return Collections.unmodifiableMap(meta); + public void setWorkload(Workload workload) { + this.workload = workload; } - public void setWorkload(Workload newWorkload) { - this.workload = newWorkload; + public int getCpuCoreCount() { + return cpuCoreCount; + } + + public double getCpuCapacity() { + return cpuCapacity; + } + + public double getTotalCPULoad() { + return totalCPULoad; + } + + public long getMemorySize() { + return memorySize; + } + + public int getGpuCoreCount() { + return gpuCoreCount; + } + + public double getGpuCapacity() { + return gpuCapacity; + } + + public long getGpuMemorySize() { + return gpuMemorySize; + } + + public List<TaskWatcher> getWatchers() { + return watchers; } @NotNull public TaskState getState() { - return state; + return TaskState.getEntries().get(stateOrdinal); } - @Nullable - public Instant getScheduledAt() { - return scheduledAt; + void setState(TaskState newState) { + if (this.getState() == newState) { + return; + } + + for (TaskWatcher watcher : watchers) { + watcher.onStateChanged(this, newState); + } + if (newState == TaskState.FAILED) { + this.numFailures++; + } else if (newState == TaskState.PAUSED) { + this.numPauses++; + } + + if ((newState == TaskState.COMPLETED) || (newState == TaskState.FAILED) || (newState == TaskState.TERMINATED)) { + this.finishedAt = this.service.getClock().millis(); + } + + this.stateOrdinal = newState.ordinal(); + } + + public int getStateOrdinal() { + return stateOrdinal; + } + + public void setStateOrdinal(int stateOrdinal) { + this.stateOrdinal = stateOrdinal; } - @Nullable - public Instant getSubmittedAt() { + public long getSubmittedAt() { return submittedAt; } - @Nullable - public Instant getFinishedAt() { + public void setSubmittedAt(long submittedAt) { + this.submittedAt = submittedAt; + } + + public long getScheduledAt() { + return scheduledAt; + } + + public void setScheduledAt(long scheduledAt) { + this.scheduledAt = scheduledAt; + } + + public long getFinishedAt() { return finishedAt; } - /** - * Return the {@link SimHost} on which the task is running or <code>null</code> if it is not running on a host. - */ - public SimHost getHost() { - return host; + public void setFinishedAt(long finishedAt) { + this.finishedAt = finishedAt; } - public String getHostName() { - return hostName; + public SimHost getHost() { + return host; } public void setHost(SimHost newHost) { this.host = newHost; if (newHost != null) { - this.hostName = newHost.getName(); + this.setHostName(newHost.getName()); } } + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + public SchedulingRequest getRequest() { + return request; + } + + public void setRequest(SchedulingRequest request) { + this.request = request; + } + public int getNumFailures() { - return this.numFailures; + return numFailures; + } + + public void setNumFailures(int numFailures) { + this.numFailures = numFailures; } public int getNumPauses() { - return this.numPauses; + return numPauses; + } + + public void setNumPauses(int numPauses) { + this.numPauses = numPauses; + } + + /// ////////////////////////////////////////////////////////////////////////////////////////////////// + /// Constructor and Public Methods + /// ////////////////////////////////////////////////////////////////////////////////////////////////// + + public ServiceTask( + int id, + String name, + long submissionTime, + long duration, + int cpuCoreCount, + double cpuCapacity, + double totalCPULoad, + long memorySize, + int gpuCoreCount, + double gpuCapacity, + long gpuMemorySize, + Workload workload, + boolean deferrable, + long deadline, + ArrayList<Integer> parents, + Set<Integer> children) { + this.id = id; + this.name = name; + this.submittedAt = submissionTime; + this.duration = duration; + this.workload = workload; + + this.cpuCoreCount = cpuCoreCount; + this.cpuCapacity = cpuCapacity; + this.totalCPULoad = totalCPULoad; + this.memorySize = memorySize; + + this.gpuCoreCount = gpuCoreCount; + this.gpuCapacity = gpuCapacity; + this.gpuMemorySize = gpuMemorySize; + + this.deferrable = deferrable; + this.deadline = deadline; + + this.parents = parents; + this.children = children; + } + + public ServiceTask copy() { + return new ServiceTask( + this.id, + this.name, + this.submittedAt, + this.duration, + this.cpuCoreCount, + this.cpuCapacity, + this.totalCPULoad, + this.memorySize, + this.gpuCoreCount, + this.gpuCapacity, + 0, + this.workload, + this.deferrable, + this.deadline, + this.parents == null ? null : new ArrayList<>(this.parents), + this.children == null ? null : Set.copyOf(this.children)); } public void start() { - switch (state) { + switch (this.getState()) { case PROVISIONING: LOGGER.debug("User tried to start task but request is already pending: doing nothing"); case RUNNING: @@ -224,7 +370,6 @@ public class ServiceTask { service.delete(this); this.workload = null; - this.flavor = null; this.setState(TaskState.DELETED); } @@ -241,38 +386,51 @@ public class ServiceTask { } public String toString() { - return "Task[uid=" + id + ",name=" + name + ",state=" + state + "]"; + return "Task[uid=" + this.id + ",name=" + this.name + ",state=" + this.getState() + "]"; } - void setState(TaskState newState) { - if (this.state == newState) { + /** + * Cancel the provisioning request if active. + */ + private void cancelProvisioningRequest() { + final SchedulingRequest request = this.request; + if (request != null) { + this.request = null; + request.setCancelled(true); + } + } + + public void removeFromParents(List<Integer> completedTasks) { + if (this.parents == null) { return; } - for (TaskWatcher watcher : watchers) { - watcher.onStateChanged(this, newState); + for (int task : completedTasks) { + this.removeFromParents(task); } - if (newState == TaskState.FAILED) { - this.numFailures++; - } else if (newState == TaskState.PAUSED) { - this.numPauses++; + } + + public void removeFromParents(int completedTask) { + if (this.parents == null) { + return; } - if ((newState == TaskState.COMPLETED) || (newState == TaskState.FAILED) || (newState == TaskState.TERMINATED)) { - this.finishedAt = this.service.getClock().instant(); + this.parents.remove(Integer.valueOf(completedTask)); + } + + public boolean hasChildren() { + if (children == null) { + return false; } - this.state = newState; + return !children.isEmpty(); } - /** - * Cancel the provisioning request if active. - */ - private void cancelProvisioningRequest() { - final SchedulingRequest request = this.request; - if (request != null) { - this.request = null; - request.setCancelled(true); + public boolean hasParents() { + if (parents == null) { + return false; } + + return !parents.isEmpty(); } } |
