Search in sources :

Example 11 with Message

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

the class TaskAssignmentStage method batchMessage.

List<Message> batchMessage(Builder keyBuilder, List<Message> messages, Map<String, Resource> resourceMap, Map<String, LiveInstance> liveInstanceMap, HelixManagerProperties properties) {
    // group messages by its CurrentState path + "/" + fromState + "/" + toState
    Map<String, Message> batchMessages = new HashMap<String, Message>();
    List<Message> outputMessages = new ArrayList<Message>();
    Iterator<Message> iter = messages.iterator();
    while (iter.hasNext()) {
        Message message = iter.next();
        String resourceName = message.getResourceName();
        Resource resource = resourceMap.get(resourceName);
        String instanceName = message.getTgtName();
        LiveInstance liveInstance = liveInstanceMap.get(instanceName);
        String participantVersion = null;
        if (liveInstance != null) {
            participantVersion = liveInstance.getHelixVersion();
        }
        if (resource == null || !resource.getBatchMessageMode() || participantVersion == null || !properties.isFeatureSupported("batch_message", participantVersion)) {
            outputMessages.add(message);
            continue;
        }
        String key = keyBuilder.currentState(message.getTgtName(), message.getTgtSessionId(), message.getResourceName()).getPath() + "/" + message.getFromState() + "/" + message.getToState();
        if (!batchMessages.containsKey(key)) {
            Message batchMessage = new Message(message.getRecord());
            batchMessage.setBatchMessageMode(true);
            outputMessages.add(batchMessage);
            batchMessages.put(key, batchMessage);
        }
        batchMessages.get(key).addPartitionName(message.getPartitionName());
    }
    return outputMessages;
}
Also used : Message(org.apache.helix.model.Message) LiveInstance(org.apache.helix.model.LiveInstance) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Resource(org.apache.helix.model.Resource)

Example 12 with Message

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

the class TaskAssignmentStage method sendMessages.

protected void sendMessages(HelixDataAccessor dataAccessor, List<Message> messages) {
    if (messages == null || messages.isEmpty()) {
        return;
    }
    Builder keyBuilder = dataAccessor.keyBuilder();
    List<PropertyKey> keys = new ArrayList<PropertyKey>();
    for (Message message : messages) {
        logger.info("Sending Message " + message.getMsgId() + " to " + message.getTgtName() + " transit " + message.getResourceName() + "." + message.getPartitionName() + "|" + message.getPartitionNames() + " from:" + message.getFromState() + " to:" + message.getToState() + ", relayMessages: " + message.getRelayMessages().size());
        if (message.hasRelayMessages()) {
            for (Message msg : message.getRelayMessages().values()) {
                logger.info("Sending Relay Message " + msg.getMsgId() + " to " + msg.getTgtName() + " transit " + msg.getResourceName() + "." + msg.getPartitionName() + "|" + msg.getPartitionNames() + " from:" + msg.getFromState() + " to:" + msg.getToState() + ", relayFrom: " + msg.getRelaySrcHost() + ", attached to message: " + message.getMsgId());
            }
        }
        keys.add(keyBuilder.message(message.getTgtName(), message.getId()));
    }
    dataAccessor.createChildren(keys, new ArrayList<>(messages));
}
Also used : Message(org.apache.helix.model.Message) Builder(org.apache.helix.PropertyKey.Builder) ArrayList(java.util.ArrayList) PropertyKey(org.apache.helix.PropertyKey)

Example 13 with Message

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

the class TestDistControllerStateModel method testReset.

@Test()
public void testReset() {
    Message message = new Message(MessageType.STATE_TRANSITION, "0");
    message.setPartitionName(clusterName);
    message.setTgtName("controller_0");
    try {
        stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
    } catch (Exception e) {
        LOG.error("Exception becoming leader from standby", e);
    }
    stateModel.reset();
}
Also used : NotificationContext(org.apache.helix.NotificationContext) Message(org.apache.helix.model.Message) Test(org.testng.annotations.Test)

Example 14 with Message

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

the class DeprecatedTaskRebalancer method computeResourceMapping.

private ResourceAssignment computeResourceMapping(String jobResource, WorkflowConfig workflowConfig, JobConfig jobCfg, ResourceAssignment prevAssignment, Collection<String> liveInstances, CurrentStateOutput currStateOutput, WorkflowContext workflowCtx, JobContext jobCtx, Set<Integer> partitionsToDropFromIs, ClusterDataCache cache) {
    TargetState jobTgtState = workflowConfig.getTargetState();
    // Update running status in workflow context
    if (jobTgtState == TargetState.STOP) {
        workflowCtx.setJobState(jobResource, TaskState.STOPPED);
        // Workflow has been stopped if all jobs are stopped
        if (isWorkflowStopped(workflowCtx, workflowConfig)) {
            workflowCtx.setWorkflowState(TaskState.STOPPED);
        }
    } else {
        workflowCtx.setJobState(jobResource, TaskState.IN_PROGRESS);
        // Workflow is in progress if any task is in progress
        workflowCtx.setWorkflowState(TaskState.IN_PROGRESS);
    }
    // Used to keep track of tasks that have already been assigned to instances.
    Set<Integer> assignedPartitions = new HashSet<Integer>();
    // Used to keep track of tasks that have failed, but whose failure is acceptable
    Set<Integer> skippedPartitions = new HashSet<Integer>();
    // Keeps a mapping of (partition) -> (instance, state)
    Map<Integer, PartitionAssignment> paMap = new TreeMap<Integer, PartitionAssignment>();
    Set<String> excludedInstances = getInstancesAssignedToOtherJobs(jobResource, workflowConfig, cache);
    // Process all the current assignments of tasks.
    Set<Integer> allPartitions = getAllTaskPartitions(jobCfg, jobCtx, workflowConfig, workflowCtx, cache);
    Map<String, SortedSet<Integer>> taskAssignments = getTaskPartitionAssignments(liveInstances, prevAssignment, allPartitions);
    long currentTime = System.currentTimeMillis();
    for (String instance : taskAssignments.keySet()) {
        if (excludedInstances.contains(instance)) {
            continue;
        }
        Set<Integer> pSet = taskAssignments.get(instance);
        // Used to keep track of partitions that are in one of the final states: COMPLETED, TIMED_OUT,
        // TASK_ERROR, ERROR.
        Set<Integer> donePartitions = new TreeSet<Integer>();
        for (int pId : pSet) {
            final String pName = pName(jobResource, pId);
            // Check for pending state transitions on this (partition, instance).
            Message pendingMessage = currStateOutput.getPendingState(jobResource, new Partition(pName), instance);
            if (pendingMessage != null) {
                // There is a pending state transition for this (partition, instance). Just copy forward
                // the state assignment from the previous ideal state.
                Map<String, String> stateMap = prevAssignment.getReplicaMap(new Partition(pName));
                if (stateMap != null) {
                    String prevState = stateMap.get(instance);
                    paMap.put(pId, new PartitionAssignment(instance, prevState));
                    assignedPartitions.add(pId);
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(String.format("Task partition %s has a pending state transition on instance %s. Using the previous ideal state which was %s.", pName, instance, prevState));
                    }
                }
                continue;
            }
            TaskPartitionState currState = TaskPartitionState.valueOf(currStateOutput.getCurrentState(jobResource, new Partition(pName), instance));
            jobCtx.setPartitionState(pId, currState);
            // Process any requested state transitions.
            String requestedStateStr = currStateOutput.getRequestedState(jobResource, new Partition(pName), instance);
            if (requestedStateStr != null && !requestedStateStr.isEmpty()) {
                TaskPartitionState requestedState = TaskPartitionState.valueOf(requestedStateStr);
                if (requestedState.equals(currState)) {
                    LOG.warn(String.format("Requested state %s is the same as the current state for instance %s.", requestedState, instance));
                }
                paMap.put(pId, new PartitionAssignment(instance, requestedState.name()));
                assignedPartitions.add(pId);
                LOG.debug(String.format("Instance %s requested a state transition to %s for partition %s.", instance, requestedState, pName));
                continue;
            }
            switch(currState) {
                case RUNNING:
                case STOPPED:
                    {
                        TaskPartitionState nextState;
                        if (jobTgtState == TargetState.START) {
                            nextState = TaskPartitionState.RUNNING;
                        } else {
                            nextState = TaskPartitionState.STOPPED;
                        }
                        paMap.put(pId, new PartitionAssignment(instance, nextState.name()));
                        assignedPartitions.add(pId);
                        LOG.debug(String.format("Setting task partition %s state to %s on instance %s.", pName, nextState, instance));
                    }
                    break;
                case COMPLETED:
                    {
                        // The task has completed on this partition. Mark as such in the context object.
                        donePartitions.add(pId);
                        LOG.debug(String.format("Task partition %s has completed with state %s. Marking as such in rebalancer context.", pName, currState));
                        partitionsToDropFromIs.add(pId);
                        markPartitionCompleted(jobCtx, pId);
                    }
                    break;
                case TIMED_OUT:
                case TASK_ERROR:
                case ERROR:
                    {
                        // The task may be rescheduled on a different instance.
                        donePartitions.add(pId);
                        LOG.debug(String.format("Task partition %s has error state %s. Marking as such in rebalancer context.", pName, currState));
                        markPartitionError(jobCtx, pId, currState, true);
                        // maximum number of attempts.
                        if (jobCtx.getPartitionNumAttempts(pId) >= jobCfg.getMaxAttemptsPerTask()) {
                            // If the user does not require this task to succeed in order for the job to succeed,
                            // then we don't have to fail the job right now
                            boolean successOptional = false;
                            String taskId = jobCtx.getTaskIdForPartition(pId);
                            if (taskId != null) {
                                TaskConfig taskConfig = jobCfg.getTaskConfig(taskId);
                                if (taskConfig != null) {
                                    successOptional = taskConfig.isSuccessOptional();
                                }
                            }
                            // to fail the job immediately
                            if (skippedPartitions.size() < jobCfg.getFailureThreshold()) {
                                successOptional = true;
                            }
                            if (!successOptional) {
                                long finishTime = currentTime;
                                workflowCtx.setJobState(jobResource, TaskState.FAILED);
                                if (workflowConfig.isTerminable()) {
                                    workflowCtx.setWorkflowState(TaskState.FAILED);
                                    workflowCtx.setFinishTime(finishTime);
                                }
                                jobCtx.setFinishTime(finishTime);
                                markAllPartitionsError(jobCtx, currState, false);
                                addAllPartitions(allPartitions, partitionsToDropFromIs);
                                return emptyAssignment(jobResource, currStateOutput);
                            } else {
                                skippedPartitions.add(pId);
                                partitionsToDropFromIs.add(pId);
                            }
                        } else {
                            // Mark the task to be started at some later time (if enabled)
                            markPartitionDelayed(jobCfg, jobCtx, pId);
                        }
                    }
                    break;
                case INIT:
                case DROPPED:
                    {
                        // currState in [INIT, DROPPED]. Do nothing, the partition is eligible to be reassigned.
                        donePartitions.add(pId);
                        LOG.debug(String.format("Task partition %s has state %s. It will be dropped from the current ideal state.", pName, currState));
                    }
                    break;
                default:
                    throw new AssertionError("Unknown enum symbol: " + currState);
            }
        }
        // Remove the set of task partitions that are completed or in one of the error states.
        pSet.removeAll(donePartitions);
    }
    // For delayed tasks, trigger a rebalance event for the closest upcoming ready time
    scheduleForNextTask(jobResource, jobCtx, currentTime);
    if (isJobComplete(jobCtx, allPartitions, skippedPartitions, jobCfg)) {
        workflowCtx.setJobState(jobResource, TaskState.COMPLETED);
        jobCtx.setFinishTime(currentTime);
        if (isWorkflowComplete(workflowCtx, workflowConfig)) {
            workflowCtx.setWorkflowState(TaskState.COMPLETED);
            workflowCtx.setFinishTime(currentTime);
        }
    }
    // Make additional task assignments if needed.
    if (jobTgtState == TargetState.START) {
        // Contains the set of task partitions that must be excluded from consideration when making
        // any new assignments.
        // This includes all completed, failed, delayed, and already assigned partitions.
        Set<Integer> excludeSet = Sets.newTreeSet(assignedPartitions);
        addCompletedPartitions(excludeSet, jobCtx, allPartitions);
        addGiveupPartitions(excludeSet, jobCtx, allPartitions, jobCfg);
        excludeSet.addAll(skippedPartitions);
        excludeSet.addAll(getNonReadyPartitions(jobCtx, currentTime));
        // Get instance->[partition, ...] mappings for the target resource.
        Map<String, SortedSet<Integer>> tgtPartitionAssignments = getTaskAssignment(currStateOutput, prevAssignment, liveInstances, jobCfg, jobCtx, workflowConfig, workflowCtx, allPartitions, cache);
        for (Map.Entry<String, SortedSet<Integer>> entry : taskAssignments.entrySet()) {
            String instance = entry.getKey();
            if (!tgtPartitionAssignments.containsKey(instance) || excludedInstances.contains(instance)) {
                continue;
            }
            // Contains the set of task partitions currently assigned to the instance.
            Set<Integer> pSet = entry.getValue();
            int numToAssign = jobCfg.getNumConcurrentTasksPerInstance() - pSet.size();
            if (numToAssign > 0) {
                List<Integer> nextPartitions = getNextPartitions(tgtPartitionAssignments.get(instance), excludeSet, numToAssign);
                for (Integer pId : nextPartitions) {
                    String pName = pName(jobResource, pId);
                    paMap.put(pId, new PartitionAssignment(instance, TaskPartitionState.RUNNING.name()));
                    excludeSet.add(pId);
                    jobCtx.setAssignedParticipant(pId, instance);
                    jobCtx.setPartitionState(pId, TaskPartitionState.INIT);
                    LOG.debug(String.format("Setting task partition %s state to %s on instance %s.", pName, TaskPartitionState.RUNNING, instance));
                }
            }
        }
    }
    // Construct a ResourceAssignment object from the map of partition assignments.
    ResourceAssignment ra = new ResourceAssignment(jobResource);
    for (Map.Entry<Integer, PartitionAssignment> e : paMap.entrySet()) {
        PartitionAssignment pa = e.getValue();
        ra.addReplicaMap(new Partition(pName(jobResource, e.getKey())), ImmutableMap.of(pa._instance, pa._state));
    }
    return ra;
}
Also used : Message(org.apache.helix.model.Message) SortedSet(java.util.SortedSet) ResourceAssignment(org.apache.helix.model.ResourceAssignment) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Partition(org.apache.helix.model.Partition) TreeMap(java.util.TreeMap) HashMap(java.util.HashMap) Map(java.util.Map) BiMap(com.google.common.collect.BiMap) ImmutableMap(com.google.common.collect.ImmutableMap) HashBiMap(com.google.common.collect.HashBiMap) TreeMap(java.util.TreeMap)

Example 15 with Message

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

the class FixedTargetTaskAssignmentCalculator method getTgtPartitionAssignment.

/**
 * Get partition assignments for the target resource, but only for the partitions of interest.
 * @param currStateOutput The current state of the instances in the cluster.
 * @param instances The instances.
 * @param tgtIs The ideal state of the target resource.
 * @param tgtStates Only partitions in this set of states will be considered. If null, partitions
 *          do not need to
 *          be in any specific state to be considered.
 * @param includeSet The set of partitions to consider.
 * @return A map of instance vs set of partition ids assigned to that instance.
 */
private static Map<String, SortedSet<Integer>> getTgtPartitionAssignment(CurrentStateOutput currStateOutput, Iterable<String> instances, IdealState tgtIs, Set<String> tgtStates, Set<Integer> includeSet, JobContext jobCtx) {
    Map<String, SortedSet<Integer>> result = new HashMap<String, SortedSet<Integer>>();
    for (String instance : instances) {
        result.put(instance, new TreeSet<Integer>());
    }
    Map<String, List<Integer>> partitionsByTarget = jobCtx.getPartitionsByTarget();
    for (String pName : tgtIs.getPartitionSet()) {
        List<Integer> partitions = partitionsByTarget.get(pName);
        if (partitions == null || partitions.size() < 1) {
            continue;
        }
        int pId = partitions.get(0);
        if (includeSet.contains(pId)) {
            for (String instance : instances) {
                Message pendingMessage = currStateOutput.getPendingState(tgtIs.getResourceName(), new Partition(pName), instance);
                if (pendingMessage != null) {
                    continue;
                }
                String s = currStateOutput.getCurrentState(tgtIs.getResourceName(), new Partition(pName), instance);
                if (s != null && (tgtStates == null || tgtStates.contains(s))) {
                    result.get(instance).add(pId);
                }
            }
        }
    }
    return result;
}
Also used : Partition(org.apache.helix.model.Partition) Message(org.apache.helix.model.Message) HashMap(java.util.HashMap) List(java.util.List) SortedSet(java.util.SortedSet)

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