Search in sources :

Example 96 with Message

use of org.apache.helix.model.Message in project helix by apache.

the class CurrentStateOutput method getPartitionCountWithState.

private Map<String, Integer> getPartitionCountWithState(String resourceStateModel, String state, Map<String, Map<Partition, Map<String, Object>>> stateMap) {
    Map<String, Integer> currentPartitionCount = new HashMap<>();
    for (String resource : stateMap.keySet()) {
        String stateModel = _resourceStateModelMap.get(resource);
        if ((stateModel != null && stateModel.equals(resourceStateModel)) || (stateModel == null && resourceStateModel == null)) {
            for (Partition partition : stateMap.get(resource).keySet()) {
                Map<String, Object> partitionMessage = stateMap.get(resource).get(partition);
                for (Map.Entry<String, Object> participantMap : partitionMessage.entrySet()) {
                    String participant = participantMap.getKey();
                    if (!currentPartitionCount.containsKey(participant)) {
                        currentPartitionCount.put(participant, 0);
                    }
                    String currState = participantMap.getValue().toString();
                    if (participantMap.getValue() instanceof Message) {
                        currState = ((Message) participantMap.getValue()).getToState();
                    }
                    if ((currState != null && currState.equals(state)) || (currState == null && state == null)) {
                        currentPartitionCount.put(participant, currentPartitionCount.get(participant) + 1);
                    }
                }
            }
        }
    }
    return currentPartitionCount;
}
Also used : Partition(org.apache.helix.model.Partition) Message(org.apache.helix.model.Message) HashMap(java.util.HashMap) Map(java.util.Map) HashMap(java.util.HashMap)

Example 97 with Message

use of org.apache.helix.model.Message in project helix by apache.

the class MessageGenerationPhase method createStateTransitionCancellationMessage.

private Message createStateTransitionCancellationMessage(HelixManager manager, Resource resource, String partitionName, String instanceName, String sessionId, String stateModelDefName, String fromState, String toState, String nextState, Message cancellationMessage, boolean isCancellationEnabled, String currentState) {
    if (isCancellationEnabled && cancellationMessage == null) {
        logger.info("Send cancellation message of the state transition for " + resource.getResourceName() + "." + partitionName + " on " + instanceName + ", currentState: " + currentState + ", nextState: " + (nextState == null ? "N/A" : nextState));
        String uuid = UUID.randomUUID().toString();
        Message message = new Message(MessageType.STATE_TRANSITION_CANCELLATION, uuid);
        message.setSrcName(manager.getInstanceName());
        message.setTgtName(instanceName);
        message.setMsgState(MessageState.NEW);
        message.setPartitionName(partitionName);
        message.setResourceName(resource.getResourceName());
        message.setFromState(fromState);
        message.setToState(toState);
        message.setTgtSessionId(sessionId);
        message.setSrcSessionId(manager.getSessionId());
        message.setStateModelDef(stateModelDefName);
        message.setStateModelFactoryName(resource.getStateModelFactoryname());
        message.setBucketSize(resource.getBucketSize());
        return message;
    }
    return null;
}
Also used : Message(org.apache.helix.model.Message)

Example 98 with Message

use of org.apache.helix.model.Message in project helix by apache.

the class MessageSelectionStage method selectMessages.

// TODO: This method deserves its own class. The class should not understand helix but
// just be able to solve the problem using the algo. I think the method is following that
// but if we don't move it to another class its quite easy to break that contract
/**
 * greedy message selection algorithm: 1) calculate CS+PS state lower/upper-bounds 2)
 * group messages by state transition and sorted by priority 3) from highest priority to
 * lowest, for each message group with the same transition add message one by one and
 * make sure state constraint is not violated update state lower/upper-bounds when a new
 * message is selected.
 *
 * @param liveInstances
 * @param currentStates
 * @param pendingMessages
 * @param messages
 * @param stateConstraints
 * @param stateTransitionPriorities
 * @param stateModelDef
 * @return
 */
List<Message> selectMessages(Map<String, LiveInstance> liveInstances, Map<String, String> currentStates, Map<String, Message> pendingMessages, List<Message> messages, Map<String, Bounds> stateConstraints, final Map<String, Integer> stateTransitionPriorities, StateModelDefinition stateModelDef, boolean p2pMessageEnabled) {
    if (messages == null || messages.isEmpty()) {
        return Collections.emptyList();
    }
    List<Message> selectedMessages = new ArrayList<>();
    Map<String, Integer> stateCnts = new HashMap<>();
    String initialState = stateModelDef.getInitialState();
    // count currentState, if no currentState, count as in initialState
    for (String instance : liveInstances.keySet()) {
        String state = initialState;
        if (currentStates.containsKey(instance)) {
            state = currentStates.get(instance);
        }
        increaseStateCnt(stateConstraints, state, stateCnts);
    }
    // count pendingStates
    for (String instance : pendingMessages.keySet()) {
        Message message = pendingMessages.get(instance);
        increaseStateCnt(stateConstraints, message.getToState(), stateCnts);
        increaseStateCnt(stateConstraints, message.getFromState(), stateCnts);
    }
    // group messages based on state transition priority
    Map<Integer, List<Message>> messagesGroupByStateTransitPriority = new TreeMap<>();
    /* record all state transition messages that transition a replica from top-state */
    List<Message> fromTopStateMessages = new LinkedList<>();
    for (Message message : messages) {
        if (message.getMsgType().equals(Message.MessageType.STATE_TRANSITION_CANCELLATION.name())) {
            selectedMessages.add(message);
            continue;
        }
        String fromState = message.getFromState();
        String toState = message.getToState();
        String transition = fromState + "-" + toState;
        int priority = Integer.MAX_VALUE;
        if (stateTransitionPriorities.containsKey(transition)) {
            priority = stateTransitionPriorities.get(transition);
        }
        if (!messagesGroupByStateTransitPriority.containsKey(priority)) {
            messagesGroupByStateTransitPriority.put(priority, new ArrayList<Message>());
        }
        messagesGroupByStateTransitPriority.get(priority).add(message);
        if (fromState.equals(stateModelDef.getTopState())) {
            fromTopStateMessages.add(message);
        }
    }
    // select messages
    for (List<Message> messageList : messagesGroupByStateTransitPriority.values()) {
        for (Message message : messageList) {
            String toState = message.getToState();
            if (stateConstraints.containsKey(toState)) {
                int newCnt = (stateCnts.containsKey(toState) ? stateCnts.get(toState) + 1 : 1);
                if (newCnt > stateConstraints.get(toState).getUpperBound()) {
                    if (p2pMessageEnabled && toState.equals(stateModelDef.getTopState()) && stateModelDef.isSingleTopStateModel()) {
                        // attach this message as a relay message to the message to transition off current top-state replica
                        if (fromTopStateMessages.size() > 0) {
                            Message fromTopStateMsg = fromTopStateMessages.get(0);
                            fromTopStateMsg.attachRelayMessage(message.getTgtName(), message);
                            fromTopStateMessages.remove(0);
                        }
                    } else {
                        // reach upper-bound of message for the topState, will not send the message
                        LOG.info("Reach upper_bound: " + stateConstraints.get(toState).getUpperBound() + ", not send message: " + message);
                    }
                    continue;
                }
            }
            increaseStateCnt(stateConstraints, message.getToState(), stateCnts);
            selectedMessages.add(message);
        }
    }
    return selectedMessages;
}
Also used : Message(org.apache.helix.model.Message) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) TreeMap(java.util.TreeMap) LinkedList(java.util.LinkedList) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList)

Example 99 with Message

use of org.apache.helix.model.Message in project helix by apache.

the class MessageThrottleStage method throttle.

private List<Message> throttle(Map<String, Integer> throttleMap, ClusterConstraints constraint, List<Message> messages, final boolean needThrottle) {
    List<Message> throttleOutputMsgs = new ArrayList<Message>();
    for (Message message : messages) {
        Map<ConstraintAttribute, String> msgAttr = ClusterConstraints.toConstraintAttributes(message);
        Set<ConstraintItem> matches = constraint.match(msgAttr);
        matches = selectConstraints(matches, msgAttr);
        boolean msgThrottled = false;
        for (ConstraintItem item : matches) {
            String key = item.filter(msgAttr).toString();
            if (!throttleMap.containsKey(key)) {
                throttleMap.put(key, valueOf(item.getConstraintValue()));
            }
            int value = throttleMap.get(key);
            throttleMap.put(key, --value);
            if (needThrottle && value < 0) {
                msgThrottled = true;
                if (LOG.isDebugEnabled()) {
                    // TODO: printout constraint item that throttles the message
                    LOG.debug("message: " + message + " is throttled by constraint: " + item);
                }
            }
        }
        if (!msgThrottled) {
            throttleOutputMsgs.add(message);
        }
    }
    return throttleOutputMsgs;
}
Also used : Message(org.apache.helix.model.Message) ArrayList(java.util.ArrayList) ConstraintItem(org.apache.helix.model.ConstraintItem) ConstraintAttribute(org.apache.helix.model.ClusterConstraints.ConstraintAttribute)

Example 100 with Message

use of org.apache.helix.model.Message in project helix by apache.

the class TaskAssignmentStage method process.

@Override
public void process(ClusterEvent event) throws Exception {
    HelixManager manager = event.getAttribute(AttributeName.helixmanager.name());
    Map<String, Resource> resourceMap = event.getAttribute(AttributeName.RESOURCES_TO_REBALANCE.name());
    MessageThrottleStageOutput messageOutput = event.getAttribute(AttributeName.MESSAGES_THROTTLE.name());
    ClusterDataCache cache = event.getAttribute(AttributeName.ClusterDataCache.name());
    Map<String, LiveInstance> liveInstanceMap = cache.getLiveInstances();
    if (manager == null || resourceMap == null || messageOutput == null || cache == null || liveInstanceMap == null) {
        throw new StageException("Missing attributes in event:" + event + ". Requires HelixManager|RESOURCES|MESSAGES_THROTTLE|DataCache|liveInstanceMap");
    }
    HelixDataAccessor dataAccessor = manager.getHelixDataAccessor();
    List<Message> messagesToSend = new ArrayList<Message>();
    for (String resourceName : resourceMap.keySet()) {
        Resource resource = resourceMap.get(resourceName);
        for (Partition partition : resource.getPartitions()) {
            List<Message> messages = messageOutput.getMessages(resourceName, partition);
            messagesToSend.addAll(messages);
        }
    }
    List<Message> outputMessages = batchMessage(dataAccessor.keyBuilder(), messagesToSend, resourceMap, liveInstanceMap, manager.getProperties());
    sendMessages(dataAccessor, outputMessages);
    // TODO: Need also count messages from task rebalancer
    if (!cache.isTaskCache()) {
        ClusterStatusMonitor clusterStatusMonitor = event.getAttribute(AttributeName.clusterStatusMonitor.name());
        if (clusterStatusMonitor != null) {
            clusterStatusMonitor.increaseMessageReceived(outputMessages);
        }
    }
    long cacheStart = System.currentTimeMillis();
    cache.cacheMessages(outputMessages);
    long cacheEnd = System.currentTimeMillis();
    logger.debug("Caching messages took " + (cacheEnd - cacheStart) + " ms");
}
Also used : Partition(org.apache.helix.model.Partition) HelixManager(org.apache.helix.HelixManager) Message(org.apache.helix.model.Message) StageException(org.apache.helix.controller.pipeline.StageException) Resource(org.apache.helix.model.Resource) ArrayList(java.util.ArrayList) ClusterStatusMonitor(org.apache.helix.monitoring.mbeans.ClusterStatusMonitor) HelixDataAccessor(org.apache.helix.HelixDataAccessor) LiveInstance(org.apache.helix.model.LiveInstance)

Aggregations

Message (org.apache.helix.model.Message)116 Test (org.testng.annotations.Test)53 ArrayList (java.util.ArrayList)36 HelixDataAccessor (org.apache.helix.HelixDataAccessor)30 Builder (org.apache.helix.PropertyKey.Builder)28 HelixManager (org.apache.helix.HelixManager)22 ZNRecord (org.apache.helix.ZNRecord)22 Criteria (org.apache.helix.Criteria)21 Date (java.util.Date)19 HashMap (java.util.HashMap)18 Partition (org.apache.helix.model.Partition)18 PropertyKey (org.apache.helix.PropertyKey)17 LiveInstance (org.apache.helix.model.LiveInstance)13 ZKHelixDataAccessor (org.apache.helix.manager.zk.ZKHelixDataAccessor)12 NotificationContext (org.apache.helix.NotificationContext)11 CurrentState (org.apache.helix.model.CurrentState)10 HelixException (org.apache.helix.HelixException)9 Resource (org.apache.helix.model.Resource)9 StringWriter (java.io.StringWriter)8 List (java.util.List)8