Search in sources :

Example 1 with LiveInstance

use of org.apache.helix.model.LiveInstance in project pinot by linkedin.

the class LiveInstancesChangeListenerImpl method onLiveInstanceChange.

@Override
public void onLiveInstanceChange(List<LiveInstance> liveInstances, NotificationContext changeContext) {
    if (connectionPool == null) {
        LOGGER.info("init hasn't been called yet on the live instances listener...");
        return;
    }
    LOGGER.info("Connection pool found, moving on...");
    for (LiveInstance instance : liveInstances) {
        String instanceId = instance.getInstanceName();
        String sessionId = instance.getSessionId();
        if (instanceId.startsWith("Broker_")) {
            LOGGER.info("skipping broker instances {}", instanceId);
            continue;
        }
        String namePortStr = instanceId.split("Server_")[1];
        String hostName = namePortStr.split("_")[0];
        int port;
        try {
            port = Integer.parseInt(namePortStr.split("_")[1]);
        } catch (Exception e) {
            LOGGER.warn("Port for server instance " + instanceId + " does not appear to be numeric", e);
            port = CommonConstants.Helix.DEFAULT_SERVER_NETTY_PORT;
        }
        ServerInstance ins = new ServerInstance(hostName, port);
        if (liveInstanceToSessionIdMap.containsKey(instanceId)) {
            // sessionId has changed
            LOGGER.info("found instance Id : {} with new session Id : {} old session Id {}", instanceId, sessionId, liveInstanceToSessionIdMap.get(instanceId));
            if (!sessionId.equals(liveInstanceToSessionIdMap.get(instanceId))) {
                try {
                    connectionPool.validatePool(ins, DO_NOT_RECREATE);
                    liveInstanceToSessionIdMap.put(instanceId, sessionId);
                } catch (Exception e) {
                    LOGGER.error("Error trying to validate & destroy dead connections for {}", instanceId, e);
                }
            }
        } else {
            LOGGER.info("found instance Id : {} with new session Id : {}", instanceId, sessionId);
            // lets first check if the connection is valid or not
            try {
                connectionPool.validatePool(ins, DO_NOT_RECREATE);
                liveInstanceToSessionIdMap.put(instanceId, sessionId);
            } catch (Exception e) {
                LOGGER.error("Error trying to destroy dead connections for {}", instanceId, e);
            }
        }
    }
}
Also used : LiveInstance(org.apache.helix.model.LiveInstance) ServerInstance(com.linkedin.pinot.common.response.ServerInstance)

Example 2 with LiveInstance

use of org.apache.helix.model.LiveInstance in project pinot by linkedin.

the class PinotHelixResourceManager method dropInstance.

/**
   * Drop the instance from helix cluster. Instance will not be dropped if:
   * - It is a live instance.
   * - Has at least one ONLINE segment.
   *
   * @param instanceName: Name of the instance to be dropped.
   * @return
   */
public PinotResourceManagerResponse dropInstance(String instanceName) {
    if (!instanceExists(instanceName)) {
        return new PinotResourceManagerResponse("Instance " + instanceName + " does not exist.", false);
    }
    HelixDataAccessor helixDataAccessor = _helixZkManager.getHelixDataAccessor();
    LiveInstance liveInstance = helixDataAccessor.getProperty(_keyBuilder.liveInstance(instanceName));
    if (liveInstance != null) {
        PropertyKey currentStatesKey = _keyBuilder.currentStates(instanceName, liveInstance.getSessionId());
        List<CurrentState> currentStates = _helixDataAccessor.getChildValues(currentStatesKey);
        if (currentStates != null) {
            for (CurrentState currentState : currentStates) {
                for (String state : currentState.getPartitionStateMap().values()) {
                    if (state.equalsIgnoreCase(SegmentOnlineOfflineStateModel.ONLINE)) {
                        return new PinotResourceManagerResponse(("Instance " + instanceName + " has online partitions"), false);
                    }
                }
            }
        } else {
            return new PinotResourceManagerResponse("Cannot drop live instance " + instanceName + " please stop the instance first.", false);
        }
    }
    // Disable the instance first.
    toogleInstance(instanceName, false, 10);
    _helixAdmin.dropInstance(_helixClusterName, getHelixInstanceConfig(instanceName));
    return new PinotResourceManagerResponse("Instance " + instanceName + " dropped.", true);
}
Also used : HelixDataAccessor(org.apache.helix.HelixDataAccessor) LiveInstance(org.apache.helix.model.LiveInstance) CurrentState(org.apache.helix.model.CurrentState) PropertyKey(org.apache.helix.PropertyKey)

Example 3 with LiveInstance

use of org.apache.helix.model.LiveInstance in project incubator-gobblin by apache.

the class GobblinHelixMessagingService method generateMessage.

@Override
public Map<InstanceType, List<Message>> generateMessage(final Criteria recipientCriteria, final Message message) {
    Map<InstanceType, List<Message>> messagesToSendMap = new HashMap<InstanceType, List<Message>>();
    InstanceType instanceType = recipientCriteria.getRecipientInstanceType();
    if (instanceType == InstanceType.CONTROLLER) {
        List<Message> messages = generateMessagesForController(message);
        messagesToSendMap.put(InstanceType.CONTROLLER, messages);
    // _dataAccessor.setControllerProperty(PropertyType.MESSAGES,
    // newMessage.getRecord(), CreateMode.PERSISTENT);
    } else if (instanceType == InstanceType.PARTICIPANT) {
        List<Message> messages = new ArrayList<Message>();
        List<Map<String, String>> matchedList = _gobblinHelixCriteriaEvaluator.evaluateCriteria(recipientCriteria, _manager);
        if (!matchedList.isEmpty()) {
            Map<String, String> sessionIdMap = new HashMap<String, String>();
            if (recipientCriteria.isSessionSpecific()) {
                HelixDataAccessor accessor = _manager.getHelixDataAccessor();
                PropertyKey.Builder keyBuilder = accessor.keyBuilder();
                List<LiveInstance> liveInstances = accessor.getChildValues(keyBuilder.liveInstances());
                for (LiveInstance liveInstance : liveInstances) {
                    sessionIdMap.put(liveInstance.getInstanceName(), liveInstance.getSessionId());
                }
            }
            for (Map<String, String> map : matchedList) {
                String id = UUID.randomUUID().toString();
                Message newMessage = new Message(message.getRecord(), id);
                String srcInstanceName = _manager.getInstanceName();
                String tgtInstanceName = map.get("instanceName");
                // Don't send message to self
                if (recipientCriteria.isSelfExcluded() && srcInstanceName.equalsIgnoreCase(tgtInstanceName)) {
                    continue;
                }
                newMessage.setSrcName(srcInstanceName);
                newMessage.setTgtName(tgtInstanceName);
                newMessage.setResourceName(map.get("resourceName"));
                newMessage.setPartitionName(map.get("partitionName"));
                if (recipientCriteria.isSessionSpecific()) {
                    newMessage.setTgtSessionId(sessionIdMap.get(tgtInstanceName));
                }
                messages.add(newMessage);
            }
            messagesToSendMap.put(InstanceType.PARTICIPANT, messages);
        }
    }
    return messagesToSendMap;
}
Also used : Message(org.apache.helix.model.Message) HashMap(java.util.HashMap) HelixDataAccessor(org.apache.helix.HelixDataAccessor) LiveInstance(org.apache.helix.model.LiveInstance) ArrayList(java.util.ArrayList) List(java.util.List) InstanceType(org.apache.helix.InstanceType) HashMap(java.util.HashMap) Map(java.util.Map)

Example 4 with LiveInstance

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

the class MessageGenerationPhase method process.

@Override
public void process(ClusterEvent event) throws Exception {
    HelixManager manager = event.getAttribute(AttributeName.helixmanager.name());
    ClusterDataCache cache = event.getAttribute(AttributeName.ClusterDataCache.name());
    Map<String, Resource> resourceMap = event.getAttribute(AttributeName.RESOURCES_TO_REBALANCE.name());
    Map<String, List<Message>> pendingMessagesToCleanUp = new HashMap<>();
    CurrentStateOutput currentStateOutput = event.getAttribute(AttributeName.CURRENT_STATE.name());
    IntermediateStateOutput intermediateStateOutput = event.getAttribute(AttributeName.INTERMEDIATE_STATE.name());
    if (manager == null || cache == null || resourceMap == null || currentStateOutput == null || intermediateStateOutput == null) {
        throw new StageException("Missing attributes in event:" + event + ". Requires HelixManager|DataCache|RESOURCES|CURRENT_STATE|INTERMEDIATE_STATE");
    }
    Map<String, LiveInstance> liveInstances = cache.getLiveInstances();
    Map<String, String> sessionIdMap = new HashMap<String, String>();
    for (LiveInstance liveInstance : liveInstances.values()) {
        sessionIdMap.put(liveInstance.getInstanceName(), liveInstance.getSessionId());
    }
    MessageGenerationOutput output = new MessageGenerationOutput();
    for (String resourceName : resourceMap.keySet()) {
        Resource resource = resourceMap.get(resourceName);
        StateModelDefinition stateModelDef = cache.getStateModelDef(resource.getStateModelDefRef());
        if (stateModelDef == null) {
            logger.error("State Model Definition null, skip generating messages for resource: " + resourceName);
            continue;
        }
        for (Partition partition : resource.getPartitions()) {
            Map<String, String> instanceStateMap = new HashMap<String, String>(intermediateStateOutput.getInstanceStateMap(resourceName, partition));
            Map<String, String> pendingStateMap = currentStateOutput.getPendingStateMap(resourceName, partition);
            for (String instance : pendingStateMap.keySet()) {
                if (!instanceStateMap.containsKey(instance)) {
                    instanceStateMap.put(instance, NO_DESIRED_STATE);
                }
            }
            // we should generate message based on the desired-state priority
            // so keep generated messages in a temp map keyed by state
            // desired-state->list of generated-messages
            Map<String, List<Message>> messageMap = new HashMap<String, List<Message>>();
            for (String instanceName : instanceStateMap.keySet()) {
                String desiredState = instanceStateMap.get(instanceName);
                String currentState = currentStateOutput.getCurrentState(resourceName, partition, instanceName);
                if (currentState == null) {
                    currentState = stateModelDef.getInitialState();
                }
                Message pendingMessage = currentStateOutput.getPendingState(resourceName, partition, instanceName);
                boolean isCancellationEnabled = cache.getClusterConfig().isStateTransitionCancelEnabled();
                Message cancellationMessage = currentStateOutput.getCancellationState(resourceName, partition, instanceName);
                String nextState = stateModelDef.getNextStateForTransition(currentState, desiredState);
                Message message = null;
                if (shouldCleanUpPendingMessage(pendingMessage, currentState, currentStateOutput.getEndTime(resourceName, partition, instanceName))) {
                    logger.info("Adding pending message {} on instance {} to clean up. Msg: {}->{}, current state of resource {}:{} is {}", pendingMessage.getMsgId(), instanceName, pendingMessage.getFromState(), pendingMessage.getToState(), resourceName, partition, currentState);
                    if (!pendingMessagesToCleanUp.containsKey(instanceName)) {
                        pendingMessagesToCleanUp.put(instanceName, new ArrayList<Message>());
                    }
                    pendingMessagesToCleanUp.get(instanceName).add(pendingMessage);
                }
                if (desiredState.equals(NO_DESIRED_STATE) || desiredState.equalsIgnoreCase(currentState)) {
                    if (desiredState.equals(NO_DESIRED_STATE) || pendingMessage != null && !currentState.equalsIgnoreCase(pendingMessage.getToState())) {
                        message = createStateTransitionCancellationMessage(manager, resource, partition.getPartitionName(), instanceName, sessionIdMap.get(instanceName), stateModelDef.getId(), pendingMessage.getFromState(), pendingMessage.getToState(), null, cancellationMessage, isCancellationEnabled, currentState);
                    }
                } else {
                    if (nextState == null) {
                        logger.error("Unable to find a next state for resource: " + resource.getResourceName() + " partition: " + partition.getPartitionName() + " from stateModelDefinition" + stateModelDef.getClass() + " from:" + currentState + " to:" + desiredState);
                        continue;
                    }
                    if (pendingMessage != null) {
                        String pendingState = pendingMessage.getToState();
                        if (nextState.equalsIgnoreCase(pendingState)) {
                            logger.debug("Message already exists for " + instanceName + " to transit " + resource.getResourceName() + "." + partition.getPartitionName() + " from " + currentState + " to " + nextState);
                        } else if (currentState.equalsIgnoreCase(pendingState)) {
                            logger.info("Message hasn't been removed for " + instanceName + " to transit " + resource.getResourceName() + "." + partition.getPartitionName() + " to " + pendingState + ", desiredState: " + desiredState);
                        } else {
                            logger.info("IdealState changed before state transition completes for " + resource.getResourceName() + "." + partition.getPartitionName() + " on " + instanceName + ", pendingState: " + pendingState + ", currentState: " + currentState + ", nextState: " + nextState);
                            message = createStateTransitionCancellationMessage(manager, resource, partition.getPartitionName(), instanceName, sessionIdMap.get(instanceName), stateModelDef.getId(), pendingMessage.getFromState(), pendingState, nextState, cancellationMessage, isCancellationEnabled, currentState);
                        }
                    } else {
                        // Create new state transition message
                        message = createStateTransitionMessage(manager, resource, partition.getPartitionName(), instanceName, currentState, nextState, sessionIdMap.get(instanceName), stateModelDef.getId());
                    }
                }
                if (message != null) {
                    IdealState idealState = cache.getIdealState(resourceName);
                    if (idealState != null && idealState.getStateModelDefRef().equalsIgnoreCase(DefaultSchedulerMessageHandlerFactory.SCHEDULER_TASK_QUEUE)) {
                        if (idealState.getRecord().getMapField(partition.getPartitionName()) != null) {
                            message.getRecord().setMapField(Message.Attributes.INNER_MESSAGE.toString(), idealState.getRecord().getMapField(partition.getPartitionName()));
                        }
                    }
                    int timeout = getTimeOut(cache.getClusterConfig(), cache.getResourceConfig(resourceName), currentState, nextState, idealState, partition);
                    if (timeout > 0) {
                        message.setExecutionTimeout(timeout);
                    }
                    message.setAttribute(Message.Attributes.ClusterEventName, event.getEventType().name());
                    // output.addMessage(resourceName, partition, message);
                    if (!messageMap.containsKey(desiredState)) {
                        messageMap.put(desiredState, new ArrayList<Message>());
                    }
                    messageMap.get(desiredState).add(message);
                }
            }
            // add generated messages to output according to state priority
            List<String> statesPriorityList = stateModelDef.getStatesPriorityList();
            for (String state : statesPriorityList) {
                if (messageMap.containsKey(state)) {
                    for (Message message : messageMap.get(state)) {
                        output.addMessage(resourceName, partition, message);
                    }
                }
            }
        }
    // end of for-each-partition
    }
    // Asynchronously clean up pending messages if necessary
    if (!pendingMessagesToCleanUp.isEmpty()) {
        schedulePendingMessageCleanUp(pendingMessagesToCleanUp, cache.getAsyncTasksThreadPool(), manager.getHelixDataAccessor());
    }
    event.addAttribute(AttributeName.MESSAGES_ALL.name(), output);
}
Also used : Partition(org.apache.helix.model.Partition) HelixManager(org.apache.helix.HelixManager) Message(org.apache.helix.model.Message) HashMap(java.util.HashMap) StageException(org.apache.helix.controller.pipeline.StageException) Resource(org.apache.helix.model.Resource) IdealState(org.apache.helix.model.IdealState) LiveInstance(org.apache.helix.model.LiveInstance) StateModelDefinition(org.apache.helix.model.StateModelDefinition) ArrayList(java.util.ArrayList) List(java.util.List)

Example 5 with LiveInstance

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

the class ClusterDataCache method setLiveInstances.

public synchronized void setLiveInstances(List<LiveInstance> liveInstances) {
    Map<String, LiveInstance> liveInstanceMap = new HashMap();
    for (LiveInstance liveInstance : liveInstances) {
        liveInstanceMap.put(liveInstance.getId(), liveInstance);
    }
    _liveInstanceCacheMap = liveInstanceMap;
    _updateInstanceOfflineTime = true;
}
Also used : LiveInstance(org.apache.helix.model.LiveInstance) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Aggregations

LiveInstance (org.apache.helix.model.LiveInstance)73 HelixDataAccessor (org.apache.helix.HelixDataAccessor)31 ZNRecord (org.apache.helix.ZNRecord)28 Builder (org.apache.helix.PropertyKey.Builder)25 Test (org.testng.annotations.Test)25 Date (java.util.Date)20 ZKHelixDataAccessor (org.apache.helix.manager.zk.ZKHelixDataAccessor)20 HashMap (java.util.HashMap)18 PropertyKey (org.apache.helix.PropertyKey)18 ArrayList (java.util.ArrayList)17 CurrentState (org.apache.helix.model.CurrentState)14 Message (org.apache.helix.model.Message)13 MockParticipantManager (org.apache.helix.integration.manager.MockParticipantManager)11 HelixManager (org.apache.helix.HelixManager)10 IdealState (org.apache.helix.model.IdealState)9 BestPossAndExtViewZkVerifier (org.apache.helix.tools.ClusterStateVerifier.BestPossAndExtViewZkVerifier)9 HelixException (org.apache.helix.HelixException)8 InstanceConfig (org.apache.helix.model.InstanceConfig)7 ClusterStateVerifier (org.apache.helix.tools.ClusterStateVerifier)7 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)6