/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.aurora.scheduler.events; import java.util.Objects; import java.util.Set; import com.google.common.base.MoreObjects; import com.google.common.base.Optional; import com.google.gson.Gson; import org.apache.aurora.gen.ScheduleStatus; import org.apache.aurora.scheduler.base.TaskGroupKey; import org.apache.aurora.scheduler.base.Tasks; import org.apache.aurora.scheduler.filter.SchedulingFilter.Veto; import org.apache.aurora.scheduler.storage.entities.IHostAttributes; import org.apache.aurora.scheduler.storage.entities.IScheduledTask; import org.apache.mesos.v1.Protos; import org.apache.mesos.v1.Protos.TaskStatus; import static java.util.Objects.requireNonNull; /** * Event notifications related to tasks. */ public interface PubsubEvent { /** * Interface with no functionality, but identifies a class as supporting task pubsub events. */ interface EventSubscriber { } /** * Event sent when tasks were deleted. */ class TasksDeleted implements PubsubEvent { private final Set<IScheduledTask> tasks; public TasksDeleted(Set<IScheduledTask> tasks) { this.tasks = requireNonNull(tasks); } public Set<IScheduledTask> getTasks() { return tasks; } @Override public boolean equals(Object o) { if (!(o instanceof TasksDeleted)) { return false; } TasksDeleted other = (TasksDeleted) o; return Objects.equals(tasks, other.tasks); } @Override public int hashCode() { return Objects.hash(tasks); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("tasks", Tasks.ids(tasks)) .toString(); } } /** * Event sent when a task changed state. * <p> * This class is final as it should only be constructed through declared factory methods. */ final class TaskStateChange implements PubsubEvent { private final IScheduledTask task; private final Optional<ScheduleStatus> oldState; private TaskStateChange(IScheduledTask task, Optional<ScheduleStatus> oldState) { this.task = requireNonNull(task); this.oldState = requireNonNull(oldState); } /** * Creates a state change event that represents the initial value of a task. * * @param task Task structure. * @return A state change event. */ public static TaskStateChange initialized(IScheduledTask task) { return new TaskStateChange(task, Optional.absent()); } /** * Creates a state change event that represents a transition from one state to another. * * @param task Current task structure. * @param oldState State the task was previously in. * @return A state change event. */ public static TaskStateChange transition(IScheduledTask task, ScheduleStatus oldState) { return new TaskStateChange(task, Optional.of(oldState)); } public String getTaskId() { return Tasks.id(task); } public Optional<ScheduleStatus> getOldState() { return oldState; } public boolean isTransition() { return oldState.isPresent(); } public IScheduledTask getTask() { return task; } public ScheduleStatus getNewState() { return task.getStatus(); } @Override public boolean equals(Object o) { if (!(o instanceof TaskStateChange)) { return false; } TaskStateChange other = (TaskStateChange) o; return Objects.equals(task, other.task) && Objects.equals(oldState, other.oldState); } @Override public int hashCode() { return Objects.hash(task, oldState); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("task", Tasks.id(task)) .add("oldState", getOldState()) .add("newState", getNewState()) .toString(); } public String toJson() { return new Gson().toJson(this); } } /** * Event sent when a host's attributes change. */ class HostAttributesChanged implements PubsubEvent { private final IHostAttributes attributes; public HostAttributesChanged(IHostAttributes attributes) { this.attributes = requireNonNull(attributes); } public IHostAttributes getAttributes() { return attributes; } @Override public int hashCode() { return attributes.hashCode(); } @Override public boolean equals(Object o) { if (!(o instanceof HostAttributesChanged)) { return false; } HostAttributesChanged other = (HostAttributesChanged) o; return Objects.equals(attributes, other.getAttributes()); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("attributes", getAttributes()) .toString(); } } /** * Event sent when a scheduling assignment was vetoed. */ class Vetoed implements PubsubEvent { private final TaskGroupKey groupKey; private final Set<Veto> vetoes; public Vetoed(TaskGroupKey groupKey, Set<Veto> vetoes) { this.groupKey = requireNonNull(groupKey); this.vetoes = requireNonNull(vetoes); } public TaskGroupKey getGroupKey() { return groupKey; } public Set<Veto> getVetoes() { return vetoes; } @Override public boolean equals(Object o) { if (!(o instanceof Vetoed)) { return false; } Vetoed other = (Vetoed) o; return Objects.equals(groupKey, other.groupKey) && Objects.equals(vetoes, other.vetoes); } @Override public int hashCode() { return Objects.hash(groupKey, vetoes); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("groupKey", groupKey) .add("vetoes", vetoes) .toString(); } } class DriverRegistered implements PubsubEvent { @Override public boolean equals(Object o) { return o != null && getClass().equals(o.getClass()); } @Override public int hashCode() { return getClass().hashCode(); } } class DriverDisconnected implements PubsubEvent { @Override public boolean equals(Object o) { return o != null && getClass().equals(o.getClass()); } @Override public int hashCode() { return getClass().hashCode(); } } class TaskStatusReceived implements PubsubEvent { private final Protos.TaskState state; private final Optional<TaskStatus.Source> source; private final Optional<TaskStatus.Reason> reason; private final Optional<Long> epochTimestampMicros; public TaskStatusReceived( Protos.TaskState state, Optional<TaskStatus.Source> source, Optional<TaskStatus.Reason> reason, Optional<Long> epochTimestampMicros) { this.state = requireNonNull(state); this.source = requireNonNull(source); this.reason = requireNonNull(reason); this.epochTimestampMicros = requireNonNull(epochTimestampMicros); } public Protos.TaskState getState() { return state; } public Optional<TaskStatus.Source> getSource() { return source; } public Optional<TaskStatus.Reason> getReason() { return reason; } public Optional<Long> getEpochTimestampMicros() { return epochTimestampMicros; } @Override public boolean equals(Object o) { if (!(o instanceof TaskStatusReceived)) { return false; } TaskStatusReceived other = (TaskStatusReceived) o; return Objects.equals(state, other.state) && Objects.equals(source, other.source) && Objects.equals(reason, other.reason) && Objects.equals(epochTimestampMicros, other.epochTimestampMicros); } @Override public int hashCode() { return Objects.hash(state, source, reason, epochTimestampMicros); } } }