/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.falcon.state;
import org.apache.falcon.entity.v0.Entity;
import org.apache.falcon.exception.InvalidStateTransitionException;
import java.util.Properties;
/**
* Represents the state of a schedulable entity.
* Implements {@link org.apache.falcon.state.StateMachine} for an entity.
*/
public class EntityState implements StateMachine<EntityState.STATE, EntityState.EVENT> {
private Entity entity;
private STATE currentState;
private Properties properties;
private static final STATE INITIAL_STATE = STATE.SUBMITTED;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
/**
* Enumerates all the valid states of a schedulable entity and the valid transitions from that state.
*/
public enum STATE implements StateMachine<EntityState.STATE, EntityState.EVENT> {
SUBMITTED {
@Override
public STATE nextTransition(EVENT event) throws InvalidStateTransitionException {
switch (event) {
case SCHEDULE:
return STATE.SCHEDULED;
case SUBMIT:
return this;
case KILL:
return STATE.KILLED;
default:
throw new InvalidStateTransitionException("Submitted entities can only be scheduled or killed.");
}
}
},
SCHEDULED {
@Override
public STATE nextTransition(EVENT event) throws InvalidStateTransitionException {
switch (event) {
case SUSPEND:
return STATE.SUSPENDED;
case SCHEDULE:
return this;
case KILL:
return STATE.KILLED;
default:
throw new InvalidStateTransitionException("Scheduled entities can only be suspended or killed.");
}
}
},
SUSPENDED {
@Override
public STATE nextTransition(EVENT event) throws InvalidStateTransitionException {
switch (event) {
case RESUME:
return STATE.SCHEDULED;
case SUSPEND:
return this;
case KILL:
return STATE.KILLED;
default:
throw new InvalidStateTransitionException("Suspended entities can only be resumed or killed.");
}
}
},
KILLED {
@Override
public STATE nextTransition(EVENT event) throws InvalidStateTransitionException {
switch (event) {
case KILL:
return STATE.KILLED;
default:
throw new InvalidStateTransitionException("Partially killed entities can only be killed.");
}
}
}
}
/**
* Enumerates all the valid events that can cause a state transition.
*/
public enum EVENT {
SUBMIT,
SCHEDULE,
SUSPEND,
RESUME,
KILL
}
/**
* Constructor.
*
* @param e - Entity
*/
public EntityState(Entity e) {
this.entity = e;
currentState = INITIAL_STATE;
}
/**
* @return - The entity
*/
public Entity getEntity() {
return entity;
}
/**
* @param e - entity
* @return - This instance
*/
public EntityState setEntity(Entity e) {
this.entity = e;
return this;
}
/**
* @return - Current state of the entity.
*/
public STATE getCurrentState() {
return currentState;
}
/**
* @param state
* @return - This instance
*/
public EntityState setCurrentState(STATE state) {
this.currentState = state;
return this;
}
@Override
public STATE nextTransition(EVENT event) throws InvalidStateTransitionException {
return currentState.nextTransition(event);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EntityState other = (EntityState) o;
if (this.getCurrentState() != null ? !this.getCurrentState().equals(other.getCurrentState())
: other.getCurrentState() != null) {
return false;
}
if (this.getEntity() != null ? !this.getEntity().equals(other.getEntity())
: other.getEntity() != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = currentState != null ? currentState.hashCode() : 0;
result = 31 * result + (entity != null ? entity.hashCode() : 0);
return result;
}
}