Search in sources :

Example 91 with HelixManager

use of org.apache.helix.HelixManager in project helix by apache.

the class PersistAssignmentStage method process.

@Override
public void process(ClusterEvent event) throws Exception {
    ClusterDataCache cache = event.getAttribute(AttributeName.ClusterDataCache.name());
    ClusterConfig clusterConfig = cache.getClusterConfig();
    if (!clusterConfig.isPersistBestPossibleAssignment() && !clusterConfig.isPersistIntermediateAssignment()) {
        return;
    }
    BestPossibleStateOutput bestPossibleAssignment = event.getAttribute(AttributeName.BEST_POSSIBLE_STATE.name());
    HelixManager helixManager = event.getAttribute(AttributeName.helixmanager.name());
    HelixDataAccessor accessor = helixManager.getHelixDataAccessor();
    PropertyKey.Builder keyBuilder = accessor.keyBuilder();
    Map<String, Resource> resourceMap = event.getAttribute(AttributeName.RESOURCES.name());
    for (String resourceId : bestPossibleAssignment.resourceSet()) {
        Resource resource = resourceMap.get(resourceId);
        if (resource != null) {
            final IdealState idealState = cache.getIdealState(resourceId);
            if (idealState == null) {
                LOG.warn("IdealState not found for resource " + resourceId);
                continue;
            }
            IdealState.RebalanceMode mode = idealState.getRebalanceMode();
            if (!mode.equals(IdealState.RebalanceMode.SEMI_AUTO) && !mode.equals(IdealState.RebalanceMode.FULL_AUTO)) {
                // do not persist assignment for resource in neither semi or full auto.
                continue;
            }
            boolean needPersist = false;
            if (mode.equals(IdealState.RebalanceMode.FULL_AUTO)) {
                // persist preference list in ful-auto mode.
                Map<String, List<String>> newLists = bestPossibleAssignment.getPreferenceLists(resourceId);
                if (newLists != null && hasPreferenceListChanged(newLists, idealState)) {
                    idealState.setPreferenceLists(newLists);
                    needPersist = true;
                }
            }
            PartitionStateMap partitionStateMap = bestPossibleAssignment.getPartitionStateMap(resourceId);
            if (clusterConfig.isPersistIntermediateAssignment()) {
                IntermediateStateOutput intermediateAssignment = event.getAttribute(AttributeName.INTERMEDIATE_STATE.name());
                partitionStateMap = intermediateAssignment.getPartitionStateMap(resourceId);
            }
            // TODO: temporary solution for Espresso/Dbus backcompatible, should remove this.
            Map<Partition, Map<String, String>> assignmentToPersist = convertAssignmentPersisted(resource, idealState, partitionStateMap.getStateMap());
            if (assignmentToPersist != null && hasInstanceMapChanged(assignmentToPersist, idealState)) {
                for (Partition partition : assignmentToPersist.keySet()) {
                    Map<String, String> instanceMap = assignmentToPersist.get(partition);
                    idealState.setInstanceStateMap(partition.getPartitionName(), instanceMap);
                }
                needPersist = true;
            }
            if (needPersist) {
                // Update instead of set to ensure any intermediate changes that the controller does not update are kept.
                accessor.updateProperty(keyBuilder.idealStates(resourceId), new DataUpdater<ZNRecord>() {

                    @Override
                    public ZNRecord update(ZNRecord current) {
                        if (current != null) {
                            // Overwrite MapFields and ListFields items with the same key.
                            // Note that default merge will keep old values in the maps or lists unchanged, which is not desired.
                            current.getMapFields().clear();
                            current.getMapFields().putAll(idealState.getRecord().getMapFields());
                            current.getListFields().putAll(idealState.getRecord().getListFields());
                        }
                        return current;
                    }
                }, idealState);
            }
        }
    }
}
Also used : Partition(org.apache.helix.model.Partition) HelixManager(org.apache.helix.HelixManager) Resource(org.apache.helix.model.Resource) IdealState(org.apache.helix.model.IdealState) PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) HelixDataAccessor(org.apache.helix.HelixDataAccessor) List(java.util.List) HashMap(java.util.HashMap) PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) Map(java.util.Map) PropertyKey(org.apache.helix.PropertyKey) ZNRecord(org.apache.helix.ZNRecord) ClusterConfig(org.apache.helix.model.ClusterConfig)

Example 92 with HelixManager

use of org.apache.helix.HelixManager in project helix by apache.

the class TargetExteralViewCalcStage method process.

@Override
public void process(ClusterEvent event) throws Exception {
    ClusterDataCache cache = event.getAttribute(AttributeName.ClusterDataCache.name());
    ClusterConfig clusterConfig = cache.getClusterConfig();
    if (cache.isTaskCache() || !clusterConfig.isTargetExternalViewEnabled()) {
        return;
    }
    HelixManager helixManager = event.getAttribute(AttributeName.helixmanager.name());
    HelixDataAccessor accessor = helixManager.getHelixDataAccessor();
    if (!accessor.getBaseDataAccessor().exists(accessor.keyBuilder().targetExternalViews().getPath(), AccessOption.PERSISTENT)) {
        accessor.getBaseDataAccessor().create(accessor.keyBuilder().targetExternalViews().getPath(), null, AccessOption.PERSISTENT);
    }
    BestPossibleStateOutput bestPossibleAssignments = event.getAttribute(AttributeName.BEST_POSSIBLE_STATE.name());
    IntermediateStateOutput intermediateAssignments = event.getAttribute(AttributeName.INTERMEDIATE_STATE.name());
    Map<String, Resource> resourceMap = event.getAttribute(AttributeName.RESOURCES.name());
    List<PropertyKey> keys = new ArrayList<>();
    List<ExternalView> targetExternalViews = new ArrayList<>();
    for (String resourceName : bestPossibleAssignments.resourceSet()) {
        if (cache.getIdealState(resourceName) == null || cache.getIdealState(resourceName).isExternalViewDisabled()) {
            continue;
        }
        Resource resource = resourceMap.get(resourceName);
        if (resource != null) {
            PartitionStateMap partitionStateMap = intermediateAssignments.getPartitionStateMap(resourceName);
            Map<String, Map<String, String>> intermediateAssignment = convertToMapFields(partitionStateMap.getStateMap());
            Map<String, List<String>> preferenceLists = bestPossibleAssignments.getPreferenceLists(resourceName);
            boolean needPersist = false;
            ExternalView targetExternalView = cache.getTargetExternalView(resourceName);
            if (targetExternalView == null) {
                targetExternalView = new ExternalView(resourceName);
                targetExternalView.getRecord().getSimpleFields().putAll(cache.getIdealState(resourceName).getRecord().getSimpleFields());
                needPersist = true;
            }
            if (preferenceLists != null && !targetExternalView.getRecord().getListFields().equals(preferenceLists)) {
                targetExternalView.getRecord().setListFields(preferenceLists);
                needPersist = true;
            }
            if (intermediateAssignment != null && !targetExternalView.getRecord().getMapFields().equals(intermediateAssignment)) {
                targetExternalView.getRecord().setMapFields(intermediateAssignment);
                needPersist = true;
            }
            if (needPersist) {
                keys.add(accessor.keyBuilder().targetExternalView(resourceName));
                targetExternalViews.add(targetExternalView);
                cache.updateTargetExternalView(resourceName, targetExternalView);
            }
        }
    }
    accessor.setChildren(keys, targetExternalViews);
}
Also used : ExternalView(org.apache.helix.model.ExternalView) HelixManager(org.apache.helix.HelixManager) Resource(org.apache.helix.model.Resource) ArrayList(java.util.ArrayList) PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) HelixDataAccessor(org.apache.helix.HelixDataAccessor) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) PartitionStateMap(org.apache.helix.controller.common.PartitionStateMap) Map(java.util.Map) PropertyKey(org.apache.helix.PropertyKey) ClusterConfig(org.apache.helix.model.ClusterConfig)

Example 93 with HelixManager

use of org.apache.helix.HelixManager 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)

Example 94 with HelixManager

use of org.apache.helix.HelixManager in project helix by apache.

the class GenericHelixController method handleEvent.

/**
 * lock-always: caller always needs to obtain an external lock before call, calls to handleEvent()
 * should be serialized
 * @param event
 */
protected void handleEvent(ClusterEvent event, ClusterDataCache cache) {
    HelixManager manager = event.getAttribute(AttributeName.helixmanager.name());
    if (manager == null) {
        logger.error("No cluster manager in event:" + event.getEventType());
        return;
    }
    if (!manager.isLeader()) {
        logger.error("Cluster manager: " + manager.getInstanceName() + " is not leader for " + manager.getClusterName() + ". Pipeline will not be invoked");
        return;
    }
    // will be excuting in un-paused mode. Which might not be the config in ZK.
    if (_paused) {
        logger.info("Cluster " + manager.getClusterName() + " is paused. Ignoring the event:" + event.getEventType());
        return;
    }
    NotificationContext context = null;
    if (event.getAttribute(AttributeName.changeContext.name()) != null) {
        context = event.getAttribute(AttributeName.changeContext.name());
    }
    if (context != null) {
        if (context.getType() == Type.FINALIZE) {
            stopRebalancingTimers();
            logger.info("Get FINALIZE notification, skip the pipeline. Event :" + event.getEventType());
            return;
        } else {
            // TODO: should be in the initialization of controller.
            if (_cache != null) {
                checkRebalancingTimer(manager, Collections.EMPTY_LIST, _cache.getClusterConfig());
            }
            if (_isMonitoring) {
                event.addAttribute(AttributeName.clusterStatusMonitor.name(), _clusterStatusMonitor);
            }
        }
    }
    // add the cache
    event.addAttribute(AttributeName.ClusterDataCache.name(), cache);
    List<Pipeline> pipelines = cache.isTaskCache() ? _taskRegistry.getPipelinesForEvent(event.getEventType()) : _registry.getPipelinesForEvent(event.getEventType());
    if (pipelines == null || pipelines.size() == 0) {
        logger.info("No " + getPipelineType(cache.isTaskCache()) + " pipeline to run for event:" + event.getEventType());
        return;
    }
    logger.info(String.format("START: Invoking %s controller pipeline for cluster %s event: %s", manager.getClusterName(), getPipelineType(cache.isTaskCache()), event.getEventType()));
    long startTime = System.currentTimeMillis();
    boolean rebalanceFail = false;
    for (Pipeline pipeline : pipelines) {
        try {
            pipeline.handle(event);
            pipeline.finish();
        } catch (Exception e) {
            logger.error("Exception while executing " + getPipelineType(cache.isTaskCache()) + "pipeline: " + pipeline + "for cluster ." + _clusterName + ". Will not continue to next pipeline", e);
            if (e instanceof HelixMetaDataAccessException) {
                rebalanceFail = true;
                // If pipeline failed due to read/write fails to zookeeper, retry the pipeline.
                cache.requireFullRefresh();
                logger.warn("Rebalance pipeline failed due to read failure from zookeeper, cluster: " + _clusterName);
                // only push a retry event when there is no pending event in the corresponding event queue.
                if (isEventQueueEmpty(cache.isTaskCache())) {
                    _continousRebalanceFailureCount++;
                    long delay = getRetryDelay(_continousRebalanceFailureCount);
                    if (delay == 0) {
                        forceRebalance(manager, ClusterEventType.RetryRebalance);
                    } else {
                        _asyncTasksThreadPool.schedule(new RebalanceTask(manager, ClusterEventType.RetryRebalance), delay, TimeUnit.MILLISECONDS);
                    }
                    logger.info("Retry rebalance pipeline with delay " + delay + "ms for cluster: " + _clusterName);
                }
            }
            _clusterStatusMonitor.reportRebalanceFailure();
            break;
        }
    }
    if (!rebalanceFail) {
        _continousRebalanceFailureCount = 0;
    }
    long endTime = System.currentTimeMillis();
    logger.info(String.format("END: Invoking %s controller pipeline for event: %s for cluster %s, took %d ms", getPipelineType(cache.isTaskCache()), event.getEventType(), manager.getClusterName(), (endTime - startTime)));
    if (!cache.isTaskCache()) {
        // report event process durations
        NotificationContext notificationContext = event.getAttribute(AttributeName.changeContext.name());
        long enqueueTime = event.getCreationTime();
        long zkCallbackTime;
        StringBuilder sb = new StringBuilder();
        if (notificationContext != null) {
            zkCallbackTime = notificationContext.getCreationTime();
            if (_isMonitoring) {
                _clusterStatusMonitor.updateClusterEventDuration(ClusterEventMonitor.PhaseName.Callback.name(), enqueueTime - zkCallbackTime);
            }
            sb.append(String.format("Callback time for event: " + event.getEventType() + " took: " + (enqueueTime - zkCallbackTime) + " ms\n"));
        }
        if (_isMonitoring) {
            _clusterStatusMonitor.updateClusterEventDuration(ClusterEventMonitor.PhaseName.InQueue.name(), startTime - enqueueTime);
            _clusterStatusMonitor.updateClusterEventDuration(ClusterEventMonitor.PhaseName.TotalProcessed.name(), endTime - startTime);
        }
        sb.append(String.format("InQueue time for event: " + event.getEventType() + " took: " + (startTime - enqueueTime) + " ms\n"));
        sb.append(String.format("TotalProcessed time for event: " + event.getEventType() + " took: " + (endTime - startTime) + " ms"));
        logger.info(sb.toString());
    } else if (_isMonitoring) {
        // report workflow status
        TaskDriver driver = new TaskDriver(manager);
        _clusterStatusMonitor.refreshWorkflowsStatus(driver);
        _clusterStatusMonitor.refreshJobsStatus(driver);
    }
    // If event handling happens before controller deactivate, the process may write unnecessary
    // MBeans to monitoring after the monitor is disabled.
    // So reset ClusterStatusMonitor according to it's status after all event handling.
    // TODO remove this once clusterStatusMonitor blocks any MBean register on isMonitoring = false.
    resetClusterStatusMonitor();
}
Also used : NotificationContext(org.apache.helix.NotificationContext) HelixManager(org.apache.helix.HelixManager) HelixMetaDataAccessException(org.apache.helix.api.exceptions.HelixMetaDataAccessException) TaskDriver(org.apache.helix.task.TaskDriver) ZkInterruptedException(org.I0Itec.zkclient.exception.ZkInterruptedException) HelixMetaDataAccessException(org.apache.helix.api.exceptions.HelixMetaDataAccessException) Pipeline(org.apache.helix.controller.pipeline.Pipeline)

Example 95 with HelixManager

use of org.apache.helix.HelixManager in project helix by apache.

the class GenericHelixController method checkLiveInstancesObservation.

/**
 * Go through the list of liveinstances in the cluster, and add currentstateChange listener and
 * Message listeners to them if they are newly added. For current state change, the observation is
 * tied to the session id of each live instance.
 */
protected void checkLiveInstancesObservation(List<LiveInstance> liveInstances, NotificationContext changeContext) {
    // construct maps for current live-instances
    Map<String, LiveInstance> curInstances = new HashMap<>();
    Map<String, LiveInstance> curSessions = new HashMap<>();
    for (LiveInstance liveInstance : liveInstances) {
        curInstances.put(liveInstance.getInstanceName(), liveInstance);
        curSessions.put(liveInstance.getSessionId(), liveInstance);
    }
    // TODO: remove the synchronization here once we move this update into dataCache.
    synchronized (_lastSeenInstances) {
        Map<String, LiveInstance> lastInstances = _lastSeenInstances.get();
        Map<String, LiveInstance> lastSessions = _lastSeenSessions.get();
        HelixManager manager = changeContext.getManager();
        Builder keyBuilder = new Builder(manager.getClusterName());
        if (lastSessions != null) {
            for (String session : lastSessions.keySet()) {
                if (!curSessions.containsKey(session)) {
                    // remove current-state listener for expired session
                    String instanceName = lastSessions.get(session).getInstanceName();
                    manager.removeListener(keyBuilder.currentStates(instanceName, session), this);
                }
            }
        }
        if (lastInstances != null) {
            for (String instance : lastInstances.keySet()) {
                if (!curInstances.containsKey(instance)) {
                    // remove message listener for disconnected instances
                    manager.removeListener(keyBuilder.messages(instance), this);
                }
            }
        }
        for (String session : curSessions.keySet()) {
            if (lastSessions == null || !lastSessions.containsKey(session)) {
                String instanceName = curSessions.get(session).getInstanceName();
                try {
                    // add current-state listeners for new sessions
                    manager.addCurrentStateChangeListener(this, instanceName, session);
                    logger.info(manager.getInstanceName() + " added current-state listener for instance: " + instanceName + ", session: " + session + ", listener: " + this);
                } catch (Exception e) {
                    logger.error("Fail to add current state listener for instance: " + instanceName + " with session: " + session, e);
                }
            }
        }
        for (String instance : curInstances.keySet()) {
            if (lastInstances == null || !lastInstances.containsKey(instance)) {
                try {
                    // add message listeners for new instances
                    manager.addMessageListener(this, instance);
                    logger.info(manager.getInstanceName() + " added message listener for " + instance + ", listener: " + this);
                } catch (Exception e) {
                    logger.error("Fail to add message listener for instance: " + instance, e);
                }
            }
        }
        // update last-seen
        _lastSeenInstances.set(curInstances);
        _lastSeenSessions.set(curSessions);
    }
}
Also used : HelixManager(org.apache.helix.HelixManager) Builder(org.apache.helix.PropertyKey.Builder) ZkInterruptedException(org.I0Itec.zkclient.exception.ZkInterruptedException) HelixMetaDataAccessException(org.apache.helix.api.exceptions.HelixMetaDataAccessException)

Aggregations

HelixManager (org.apache.helix.HelixManager)105 Test (org.testng.annotations.Test)44 HelixDataAccessor (org.apache.helix.HelixDataAccessor)35 ZNRecord (org.apache.helix.ZNRecord)27 Message (org.apache.helix.model.Message)23 PropertyKey (org.apache.helix.PropertyKey)20 Date (java.util.Date)18 ZKHelixDataAccessor (org.apache.helix.manager.zk.ZKHelixDataAccessor)17 Builder (org.apache.helix.PropertyKey.Builder)16 ArrayList (java.util.ArrayList)14 HashMap (java.util.HashMap)12 ExternalView (org.apache.helix.model.ExternalView)11 NotificationContext (org.apache.helix.NotificationContext)10 LiveInstance (org.apache.helix.model.LiveInstance)10 IdealState (org.apache.helix.model.IdealState)9 List (java.util.List)8 Criteria (org.apache.helix.Criteria)8 HelixAdmin (org.apache.helix.HelixAdmin)8 ZKHelixManager (org.apache.helix.manager.zk.ZKHelixManager)8 StringWriter (java.io.StringWriter)7