}
MessageOutput output = new MessageOutput();
for (ResourceId resourceId : resourceMap.keySet()) {
ResourceConfig resourceConfig = resourceMap.get(resourceId);
int bucketSize = 0;
bucketSize = resourceConfig.getIdealState().getBucketSize();
IdealState idealState = resourceConfig.getIdealState();
StateModelDefinition stateModelDef = stateModelDefMap.get(idealState.getStateModelDefId());
ResourceAssignment resourceAssignment =
bestPossibleStateOutput.getResourceAssignment(resourceId);
for (PartitionId subUnitId : resourceAssignment.getMappedPartitionIds()) {
Map<ParticipantId, State> instanceStateMap = resourceAssignment.getReplicaMap(subUnitId);
// we should generate message based on the desired-state priority
// so keep generated messages in a temp map keyed by state
// desired-state->list of generated-messages
Map<State, List<Message>> messageMap = new HashMap<State, List<Message>>();
for (ParticipantId participantId : instanceStateMap.keySet()) {
State desiredState = instanceStateMap.get(participantId);
State currentState =
currentStateOutput.getCurrentState(resourceId, subUnitId, participantId);
if (currentState == null) {
currentState = stateModelDef.getTypedInitialState();
}
if (desiredState.equals(currentState)) {
continue;
}
State pendingState =
currentStateOutput.getPendingState(resourceId, subUnitId, participantId);
// TODO fix it
State nextState = stateModelDef.getNextStateForTransition(currentState, desiredState);
if (nextState == null) {
LOG.error("Unable to find a next state for partition: " + subUnitId
+ " from stateModelDefinition" + stateModelDef.getClass() + " from:" + currentState
+ " to:" + desiredState);
continue;
}
if (pendingState != null) {
if (nextState.equals(pendingState)) {
LOG.debug("Message already exists for " + participantId + " to transit " + subUnitId
+ " from " + currentState + " to " + nextState);
} else if (currentState.equals(pendingState)) {
LOG.info("Message hasn't been removed for " + participantId + " to transit"
+ subUnitId + " to " + pendingState + ", desiredState: " + desiredState);
} else {
LOG.info("IdealState changed before state transition completes for " + subUnitId
+ " on " + participantId + ", pendingState: " + pendingState + ", currentState: "
+ currentState + ", nextState: " + nextState);
}
} else {
// TODO check if instance is alive
SessionId sessionId =
SessionId.from(cluster.getLiveParticipantMap().get(participantId).getLiveInstance()
.getSessionId());
Message message =
createMessage(manager, resourceId, subUnitId, participantId, currentState,
nextState, sessionId, StateModelDefId.from(stateModelDef.getId()),
idealState.getStateModelFactoryId(), bucketSize);
// TODO refactor get/set timeout/inner-message
if (idealState != null
&& idealState.getStateModelDefId().equalsIgnoreCase(
StateModelDefId.SchedulerTaskQueue)) {
if (resourceConfig.getSubUnitSet().size() > 0) {
// TODO refactor it -- we need a way to read in scheduler tasks a priori
Message innerMsg =
resourceConfig.getSchedulerTaskConfig().getInnerMessage(subUnitId);
if (innerMsg != null) {
message.setInnerMessage(innerMsg);
}
}
}
// Set timeout if needed
String stateTransition =
String.format("%s-%s_%s", currentState, nextState,
Message.Attributes.TIMEOUT.name());
SchedulerTaskConfig schedulerTaskConfig = resourceConfig.getSchedulerTaskConfig();
if (schedulerTaskConfig != null) {
int timeout = schedulerTaskConfig.getTimeout(stateTransition, subUnitId);
if (timeout > 0) {
message.setExecutionTimeout(timeout);
}