use of org.apache.helix.model.Message in project helix by apache.
the class MessageSelectionStage method process.
@Override
public void process(ClusterEvent event) throws Exception {
ClusterDataCache cache = event.getAttribute(AttributeName.ClusterDataCache.name());
Map<String, Resource> resourceMap = event.getAttribute(AttributeName.RESOURCES.name());
CurrentStateOutput currentStateOutput = event.getAttribute(AttributeName.CURRENT_STATE.name());
MessageGenerationOutput messageGenOutput = event.getAttribute(AttributeName.MESSAGES_ALL.name());
if (cache == null || resourceMap == null || currentStateOutput == null || messageGenOutput == null) {
throw new StageException("Missing attributes in event:" + event + ". Requires DataCache|RESOURCES|CURRENT_STATE|MESSAGES_ALL");
}
MessageSelectionStageOutput output = new MessageSelectionStageOutput();
for (String resourceName : resourceMap.keySet()) {
Resource resource = resourceMap.get(resourceName);
StateModelDefinition stateModelDef = cache.getStateModelDef(resource.getStateModelDefRef());
Map<String, Integer> stateTransitionPriorities = getStateTransitionPriorityMap(stateModelDef);
IdealState idealState = cache.getIdealState(resourceName);
Map<String, Bounds> stateConstraints = computeStateConstraints(stateModelDef, idealState, cache);
for (Partition partition : resource.getPartitions()) {
List<Message> messages = messageGenOutput.getMessages(resourceName, partition);
List<Message> selectedMessages = selectMessages(cache.getLiveInstances(), currentStateOutput.getCurrentStateMap(resourceName, partition), currentStateOutput.getPendingMessageMap(resourceName, partition), messages, stateConstraints, stateTransitionPriorities, stateModelDef, resource.isP2PMessageEnabled());
output.addMessages(resourceName, partition, selectedMessages);
}
}
event.addAttribute(AttributeName.MESSAGES_SELECTED.name(), output);
}
use of org.apache.helix.model.Message in project helix by apache.
the class MessageThrottleStage method process.
@Override
public void process(ClusterEvent event) throws Exception {
ClusterDataCache cache = event.getAttribute(AttributeName.ClusterDataCache.name());
MessageSelectionStageOutput msgSelectionOutput = event.getAttribute(AttributeName.MESSAGES_SELECTED.name());
Map<String, Resource> resourceMap = event.getAttribute(AttributeName.RESOURCES.name());
if (cache == null || resourceMap == null || msgSelectionOutput == null) {
throw new StageException("Missing attributes in event: " + event + ". Requires ClusterDataCache|RESOURCES|MESSAGES_SELECTED");
}
MessageThrottleStageOutput output = new MessageThrottleStageOutput();
ClusterConstraints constraint = cache.getConstraint(ConstraintType.MESSAGE_CONSTRAINT);
Map<String, Integer> throttleCounterMap = new HashMap<String, Integer>();
if (constraint != null) {
// go through all pending messages, they should be counted but not throttled
for (String instance : cache.getLiveInstances().keySet()) {
throttle(throttleCounterMap, constraint, new ArrayList<Message>(cache.getMessages(instance).values()), false);
}
}
// assume messages should be sorted by state transition priority in messageSelection stage
for (String resourceName : resourceMap.keySet()) {
Resource resource = resourceMap.get(resourceName);
for (Partition partition : resource.getPartitions()) {
List<Message> messages = msgSelectionOutput.getMessages(resourceName, partition);
if (constraint != null && messages != null && messages.size() > 0) {
messages = throttle(throttleCounterMap, constraint, messages, true);
}
output.addMessages(resourceName, partition, messages);
}
}
event.addAttribute(AttributeName.MESSAGES_THROTTLE.name(), output);
}
use of org.apache.helix.model.Message in project helix by apache.
the class CurrentStateComputationStage method updatePendingMessages.
// update all pending messages to CurrentStateOutput.
private void updatePendingMessages(LiveInstance instance, Collection<Message> pendingMessages, CurrentStateOutput currentStateOutput, Map<String, Resource> resourceMap) {
String instanceName = instance.getInstanceName();
String instanceSessionId = instance.getSessionId();
// update all pending messages
for (Message message : pendingMessages) {
if (!MessageType.STATE_TRANSITION.name().equalsIgnoreCase(message.getMsgType()) && !MessageType.STATE_TRANSITION_CANCELLATION.name().equalsIgnoreCase(message.getMsgType())) {
continue;
}
if (!instanceSessionId.equals(message.getTgtSessionId())) {
continue;
}
String resourceName = message.getResourceName();
Resource resource = resourceMap.get(resourceName);
if (resource == null) {
continue;
}
if (!message.getBatchMessageMode()) {
String partitionName = message.getPartitionName();
Partition partition = resource.getPartition(partitionName);
if (partition != null) {
setMessageState(currentStateOutput, resourceName, partition, instanceName, message);
} else {
// log
}
} else {
List<String> partitionNames = message.getPartitionNames();
if (!partitionNames.isEmpty()) {
for (String partitionName : partitionNames) {
Partition partition = resource.getPartition(partitionName);
if (partition != null) {
setMessageState(currentStateOutput, resourceName, partition, instanceName, message);
} else {
// log
}
}
}
}
}
}
use of org.apache.helix.model.Message in project helix by apache.
the class InstanceMessagesCache method updateRelayMessages.
// update all valid relay messages attached to existing state transition messages into message map.
public void updateRelayMessages(Map<String, LiveInstance> liveInstanceMap, Map<String, Map<String, Map<String, CurrentState>>> currentStateMap) {
List<Message> relayMessages = new ArrayList<>();
for (String instance : _messageMap.keySet()) {
Map<String, Message> instanceMessages = _messageMap.get(instance);
Map<String, Map<String, CurrentState>> instanceCurrentStateMap = currentStateMap.get(instance);
if (instanceCurrentStateMap == null) {
continue;
}
for (Message message : instanceMessages.values()) {
if (message.hasRelayMessages()) {
String sessionId = message.getTgtSessionId();
String resourceName = message.getResourceName();
String partitionName = message.getPartitionName();
String targetState = message.getToState();
String instanceSessionId = liveInstanceMap.get(instance).getSessionId();
if (!instanceSessionId.equals(sessionId)) {
LOG.info("Instance SessionId does not match, ignore relay messages attached to message " + message.getId());
continue;
}
Map<String, CurrentState> sessionCurrentStateMap = instanceCurrentStateMap.get(sessionId);
if (sessionCurrentStateMap == null) {
LOG.info("No sessionCurrentStateMap found, ignore relay messages attached to message " + message.getId());
continue;
}
CurrentState currentState = sessionCurrentStateMap.get(resourceName);
if (currentState == null || !targetState.equals(currentState.getState(partitionName))) {
LOG.info("CurrentState " + currentState + " do not match the target state of the message, ignore relay messages attached to message " + message.getId());
continue;
}
long transitionCompleteTime = currentState.getEndTime(partitionName);
for (Message relayMsg : message.getRelayMessages().values()) {
relayMsg.setRelayTime(transitionCompleteTime);
if (!relayMsg.isExpired()) {
relayMessages.add(relayMsg);
} else {
LOG.info("Relay message " + relayMsg.getId() + " already expired, ignore it!");
}
}
}
}
}
for (Message message : relayMessages) {
String instance = message.getTgtName();
Map<String, Message> instanceMessages = _messageMap.get(instance);
if (instanceMessages == null) {
instanceMessages = new HashMap<>();
_messageMap.put(instance, instanceMessages);
}
instanceMessages.put(message.getId(), message);
}
}
use of org.apache.helix.model.Message in project helix by apache.
the class InstanceMessagesCache method refresh.
/**
* This refreshes all pending messages in the cluster by re-fetching the data from zookeeper in an
* efficient way
* current state must be refreshed before refreshing relay messages because we need to use current
* state to validate all relay messages.
*
* @param accessor
* @param liveInstanceMap
*
* @return
*/
public boolean refresh(HelixDataAccessor accessor, Map<String, LiveInstance> liveInstanceMap) {
LOG.info("START: InstanceMessagesCache.refresh()");
long startTime = System.currentTimeMillis();
PropertyKey.Builder keyBuilder = accessor.keyBuilder();
Map<String, Map<String, Message>> msgMap = new HashMap<>();
List<PropertyKey> newMessageKeys = Lists.newLinkedList();
long purgeSum = 0;
for (String instanceName : liveInstanceMap.keySet()) {
// get the cache
Map<String, Message> cachedMap = _messageCache.get(instanceName);
if (cachedMap == null) {
cachedMap = Maps.newHashMap();
_messageCache.put(instanceName, cachedMap);
}
msgMap.put(instanceName, cachedMap);
// get the current names
Set<String> messageNames = Sets.newHashSet(accessor.getChildNames(keyBuilder.messages(instanceName)));
long purgeStart = System.currentTimeMillis();
// clear stale names
Iterator<String> cachedNamesIter = cachedMap.keySet().iterator();
while (cachedNamesIter.hasNext()) {
String messageName = cachedNamesIter.next();
if (!messageNames.contains(messageName)) {
cachedNamesIter.remove();
}
}
long purgeEnd = System.currentTimeMillis();
purgeSum += purgeEnd - purgeStart;
// get the keys for the new messages
for (String messageName : messageNames) {
if (!cachedMap.containsKey(messageName)) {
newMessageKeys.add(keyBuilder.message(instanceName, messageName));
}
}
}
// get the new messages
if (newMessageKeys.size() > 0) {
List<Message> newMessages = accessor.getProperty(newMessageKeys, true);
for (Message message : newMessages) {
if (message != null) {
Map<String, Message> cachedMap = _messageCache.get(message.getTgtName());
cachedMap.put(message.getId(), message);
}
}
}
_messageMap = Collections.unmodifiableMap(msgMap);
if (LOG.isDebugEnabled()) {
LOG.debug("Message purge took: " + purgeSum);
LOG.debug("# of Messages read from ZooKeeper " + newMessageKeys.size() + ". took " + (System.currentTimeMillis() - startTime) + " ms.");
}
return true;
}
Aggregations