Participant participant = readParticipant(participantId);
if (!participant.isAlive()) {
LOG.error("Cannot reset partitions because the participant is not running");
return false;
}
RunningInstance runningInstance = participant.getRunningInstance();
// check that the resource exists
ResourceAccessor resourceAccessor = resourceAccessor();
Resource resource = resourceAccessor.readResource(resourceId);
if (resource == null || resource.getRebalancerConfig() == null) {
LOG.error("Cannot reset partitions because the resource is not present");
return false;
}
// need the rebalancer context for the resource
RebalancerContext context =
resource.getRebalancerConfig().getRebalancerContext(RebalancerContext.class);
if (context == null) {
LOG.error("Rebalancer context for resource does not exist");
return false;
}
// ensure that all partitions to reset exist
Set<PartitionId> partitionSet = ImmutableSet.copyOf(context.getSubUnitIdSet());
if (!partitionSet.containsAll(resetPartitionIdSet)) {
LOG.error("Not all of the specified partitions to reset exist for the resource");
return false;
}
// check for a valid current state that has all specified partitions in ERROR state
CurrentState currentState = participant.getCurrentStateMap().get(resourceId);
if (currentState == null) {
LOG.error("The participant does not have a current state for the resource");
return false;
}
for (PartitionId partitionId : resetPartitionIdSet) {
if (!currentState.getState(partitionId).equals(State.from(HelixDefinedState.ERROR))) {
LOG.error("Partition " + partitionId + " is not in error state, aborting reset");
return false;
}
}
// make sure that there are no pending transition messages
for (Message message : participant.getMessageMap().values()) {
if (!MessageType.STATE_TRANSITION.toString().equalsIgnoreCase(message.getMsgType())
|| !runningInstance.getSessionId().equals(message.getTypedTgtSessionId())
|| !resourceId.equals(message.getResourceId())
|| !resetPartitionIdSet.contains(message.getPartitionId())) {
continue;
}
LOG.error("Cannot reset partitions because of the following pending message: " + message);
return false;
}
// set up the source id
String adminName = null;
try {
adminName = InetAddress.getLocalHost().getCanonicalHostName() + "-ADMIN";
} catch (UnknownHostException e) {
// can ignore it
if (LOG.isInfoEnabled()) {
LOG.info("Unable to get host name. Will set it to UNKNOWN, mostly ignorable", e);
}
adminName = "UNKNOWN";
}
// build messages to signal the transition
StateModelDefId stateModelDefId = context.getStateModelDefId();
StateModelDefinition stateModelDef =
_accessor.getProperty(_keyBuilder.stateModelDef(stateModelDefId.stringify()));
Map<MessageId, Message> messageMap = Maps.newHashMap();
for (PartitionId partitionId : resetPartitionIdSet) {
// send ERROR to initialState message
MessageId msgId = MessageId.from(UUID.randomUUID().toString());
Message message = new Message(MessageType.STATE_TRANSITION, msgId);
message.setSrcName(adminName);
message.setTgtName(participantId.stringify());
message.setMsgState(MessageState.NEW);
message.setPartitionId(partitionId);
message.setResourceId(resourceId);
message.setTgtSessionId(runningInstance.getSessionId());
message.setStateModelDef(stateModelDefId);
message.setFromState(State.from(HelixDefinedState.ERROR.toString()));
message.setToState(stateModelDef.getTypedInitialState());
message.setStateModelFactoryId(context.getStateModelFactoryId());