com.baidu.rigel.biplatform.tesseract.node.service.impl.IsNodeServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.baidu.rigel.biplatform.tesseract.node.service.impl.IsNodeServiceImpl.java

Source

/**
 * Copyright (c) 2014 Baidu, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.baidu.rigel.biplatform.tesseract.node.service.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baidu.rigel.biplatform.ac.util.Md5Util;
import com.baidu.rigel.biplatform.tesseract.isservice.meta.IndexShard;
import com.baidu.rigel.biplatform.tesseract.node.meta.Node;
import com.baidu.rigel.biplatform.tesseract.node.meta.NodeState;
import com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService;
import com.baidu.rigel.biplatform.tesseract.store.service.impl.AbstractMetaService;
import com.baidu.rigel.biplatform.tesseract.util.FileUtils;
import com.baidu.rigel.biplatform.tesseract.util.isservice.LogInfoConstants;

/**
 * 
 * ISNodeServiceAbstractMetaService?
 * 
 * @author lijin
 *
 */
@Service("isNodeService")
public class IsNodeServiceImpl extends AbstractMetaService implements IsNodeService {
    /**
     * ? ???
     */
    @Value("${indexServer.nodeStateUpdateMaxIntervalTime}")
    private long nodeStateUpdateMaxIntervalTime;

    @Resource
    private Node node;
    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(IsNodeServiceImpl.class);

    @Override
    public Map<Node, Integer> assignFreeNode(int blockCount, String clusterName) {
        List<Node> currentNodeList = getNodeListByClusterName(clusterName);
        Map<Node, Integer> result = assignFreeNodeByNodeList(currentNodeList, blockCount, clusterName);
        return result;
    }

    /* (non-Javadoc)
    * @see com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#assignFreeNodeForReplica(int, java.lang.String, java.lang.String)
    */
    @Override
    public Map<String, Node> assignFreeNodeForReplica(int blockCount, String nodeKey, String clusterName) {
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_BEGIN, "assignFreeNodeForReplica",
                "[blockCount:" + blockCount + "][nodeKey:" + nodeKey + "]"));
        List<Node> currentNodeList = getNodeListByClusterName(clusterName);
        sortNodeListByFreeBlockCount(currentNodeList);
        Map<String, Node> result = new HashMap<String, Node>();
        if (blockCount < 1) {
            return new HashMap<String, Node>();
        }
        for (Node currNode : currentNodeList) {
            if (currNode.getNodeState().equals(NodeState.NODE_AVAILABLE) && !currNode.getNodeKey().equals(nodeKey)
                    && currNode.getFreeBlockNum() > 0) {
                result.put(currNode.getNodeKey(), currNode);
                if (result.size() == blockCount) {
                    break;
                }
            }
        }
        if (result.size() > 0) {
            LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_END, "assignFreeNodeForReplica",
                    "[blockCount:" + blockCount + "][nodeKey:" + nodeKey + "]",
                    "assign node success,node count:" + result.size()));
        }
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_END, "assignFreeNodeForReplica",
                "[blockCount:" + blockCount + "][nodeKey:" + nodeKey + "]"));
        return result;
    }

    @Override
    public Map<Node, Integer> assignFreeNodeByNodeList(List<Node> existNodeList, int blockCount,
            String clusterName) {
        if (existNodeList == null || existNodeList.size() == 0) {
            return assignFreeNode(blockCount, clusterName);
        }
        Map<Node, Integer> result = new HashMap<Node, Integer>();
        sortNodeListByFreeBlockCount(existNodeList);
        int blockCountLeft = blockCount;
        for (int i = 0; (i < existNodeList.size() && blockCountLeft > 0); i++) {
            if (existNodeList.get(i).getFreeBlockNum() > 0
                    && existNodeList.get(i).getNodeState().equals(NodeState.NODE_AVAILABLE)) {
                Node currNode = existNodeList.get(i);
                int currBlockCount = currNode.getFreeBlockNum() > blockCountLeft ? blockCountLeft
                        : currNode.getFreeBlockNum();
                // ??
                currNode.setCurrBlockUsed(currNode.getCurrBlockUsed() + currBlockCount);

                result.put(currNode, currBlockCount);
                this.saveOrUpdateNodeInfo(currNode);
                blockCountLeft = blockCountLeft - currBlockCount;

            }
        }
        if (blockCountLeft > 0) {
            LOGGER.info("No more Node for another " + blockCountLeft + " blocks");
        }
        return result;
    }

    /**
     * 
     * ????
     * 
     * @param nodeList
     *            ?
     */
    private void sortNodeListByFreeBlockCount(List<Node> nodeList) {
        if (nodeList == null || nodeList.size() == 0) {
            return;
        }
        nodeList.sort(new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {

                if (o1 != null && o2 != null) {
                    if (o1.getFreeBlockNum() > o2.getFreeBlockNum()) {
                        return -1;
                    } else if (o1.getFreeBlockNum() != 0 && o1.getFreeBlockNum() == o2.getFreeBlockNum()) {
                        return 0;
                    } else {
                        return 1;
                    }
                } else if (o1 == null && o2 != null) {
                    return 1;
                } else if (o1 != null && o2 == null) {
                    return -1;
                }
                return 0;
            }
        });
        return;
    }

    @Override
    public List<Node> getNodeListByClusterName(String clusterName) {
        if (StringUtils.isEmpty(clusterName)) {
            throw new IllegalArgumentException();
        }
        String storeKey = Md5Util.encode(clusterName);
        List<Node> result = new ArrayList<Node>();
        result = super.getStoreMetaListByStoreKey(Node.getDataStoreName(), storeKey);
        if (result == null) {
            LOGGER.info("Can not find any node for Cluster:[" + clusterName + "]");
        }
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#
     * getNodeByCurrNode(com.baidu.rigel.biplatform.tesseract.node.meta.Node)
     */
    @Override
    public Node getNodeByCurrNode(Node node) {
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_BEGIN, "getNodeByCurrNode",
                "[node:" + node + "]"));
        if (node == null || StringUtils.isEmpty(node.getAddress()) || node.getPort() <= 0
                || StringUtils.isEmpty(node.getClusterName())) {
            LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_EXCEPTION, "getNodeByIpAndPort",
                    "[node:" + node + "]"));
            throw new IllegalArgumentException();
        }
        List<Node> nodeList = this.getNodeListByClusterName(node.getClusterName());
        Node result = null;
        if (nodeList != null) {
            for (Node currNode : nodeList) {
                if (currNode.equals(node)) {
                    result = currNode;
                    break;
                }
            }
        }
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_END, "getNodeByIpAndPort",
                "[node:" + node + "]"));
        return result;
    }

    public Node getNodeByIpAndPort(Node node, String clusterName) {
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_BEGIN, "getNodeByIpAndPort",
                "[node:" + node + "][clusterName:" + clusterName + "]"));
        if (node == null || StringUtils.isEmpty(node.getAddress()) || node.getPort() <= 0
                || StringUtils.isEmpty(clusterName)) {
            LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_EXCEPTION, "getNodeByIpAndPort",
                    "[node:" + node + "][clusterName:" + clusterName + "]"));
            throw new IllegalArgumentException();
        }
        List<Node> nodeList = this.getNodeListByClusterName(clusterName);
        Node result = null;
        if (nodeList != null) {
            for (Node currNode : nodeList) {
                if (currNode.equals(node)) {
                    result = currNode;
                    break;
                }
            }
        }
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_END, "getNodeByIpAndPort",
                "[node:" + node + "][clusterName:" + clusterName + "]"));
        return result;
    }

    @Override
    public boolean saveOrUpdateNodeInfo(Node node) {
        node.setLastStateUpdateTime(System.currentTimeMillis());
        return super.saveOrUpdateMetaStore(node, Node.getDataStoreName());
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.baidu.rigel.biplatform.tesseract.node.service.ISNodeService#
     * getAvailableNodeListByClusterName(java.lang.String)
     */
    @Override
    public List<Node> getAvailableNodeListByClusterName(String clusterName) {
        List<Node> result = getNodeListByClusterName(clusterName);
        if (result == null) {
            LOGGER.info("Can not find any node for Cluster:[" + clusterName + "]");
        }
        Iterator<Node> it = result.iterator();
        while (it.hasNext()) {
            Node node = it.next();
            if (node.getNodeState() == null || !node.getNodeState().equals(NodeState.NODE_AVAILABLE)) {
                it.remove();
            }
        }

        return result;
    }

    /*
     * (non-Javadoc)
     * @see com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#getNodeMapByClusterName(java.lang.String)
     */
    @Override
    public Map<String, Node> getNodeMapByClusterName(String clusterName, boolean isAvailable) {
        List<Node> resultList = getNodeListByClusterName(clusterName);
        Map<String, Node> resultMap = new HashMap<String, Node>();
        if (resultList == null) {
            LOGGER.info("Can not find any node for Cluster:[" + clusterName + "]");
        }
        Iterator<Node> it = resultList.iterator();
        while (it.hasNext()) {
            Node node = it.next();
            if (isAvailable && node.getNodeState().equals(NodeState.NODE_AVAILABLE) || !isAvailable) {
                resultMap.put(node.getNodeKey(), node);
            }

        }

        return resultMap;
    }

    /*
     * (non-Javadoc)
     * @see com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#getNodeMapByNodeKey(java.lang.String, java.util.List)
     */
    @Override
    public Map<String, Node> getNodeMapByNodeKey(String clusterName, List<String> nodeKeyList,
            boolean isAvailable) {
        //s1.get all node info of this cluster
        Map<String, Node> clusterNodeMap = getNodeMapByClusterName(clusterName, isAvailable);
        //s2.init resultset
        Map<String, Node> result = new HashMap<String, Node>();
        //s3.get proper result depend on params
        if (MapUtils.isNotEmpty(clusterNodeMap) && CollectionUtils.isNotEmpty(nodeKeyList)) {
            for (String nodeKey : nodeKeyList) {
                if (clusterNodeMap.containsKey(nodeKey)) {
                    result.put(nodeKey, clusterNodeMap.get(nodeKey));
                } else {
                    LOGGER.info("Can not find any node for Cluster:[" + clusterName + "] with nodeKey:[" + nodeKey
                            + "]");
                }
            }
        } else {
            LOGGER.info("Can not find any node for Cluster:[" + clusterName + "] with nodeKeyList:[" + nodeKeyList
                    + "]");
        }

        return result;
    }

    /* (non-Javadoc)
    * @see com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#getNodeByNodeKey(java.lang.String, java.lang.String, boolean)
    */
    @Override
    public Node getNodeByNodeKey(String clusterName, String nodeKey, boolean isAvailable) {
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_BEGIN, "getNodeByNodeKey",
                "[clusterName:" + clusterName + "][nodeKey:" + nodeKey + "][isAvailable:" + isAvailable + "]"));

        if (StringUtils.isEmpty(nodeKey) || StringUtils.isEmpty(clusterName)) {
            LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_PROCESS, "getNodeByNodeKey",
                    "[clusterName:" + clusterName + "][nodeKey:" + nodeKey + "][isAvailable:" + isAvailable + "]",
                    "param illegal"));
            return null;
        }
        List<String> nodeKeyList = new ArrayList<String>();
        nodeKeyList.add(nodeKey);
        Map<String, Node> nodeMap = getNodeMapByNodeKey(clusterName, nodeKeyList, isAvailable);
        if (MapUtils.isNotEmpty(nodeMap) && nodeMap.containsKey(nodeKey)) {
            return nodeMap.get(nodeKey);
        }
        return null;
    }

    /*
      * (non-Javadoc)
      * 
      * @see com.baidu.rigel.biplatform.tesseract.node.service.ISNodeService#
      * getAvailableNodeListByIndexShard
      * (com.baidu.rigel.biplatform.tesseract.isservice.meta.IndexShard)
      */
    @Override
    public List<Node> getAvailableNodeListByIndexShard(IndexShard idxShard, String clusterName) {
        if (idxShard == null || StringUtils.isEmpty(idxShard.getNodeKey())
                && CollectionUtils.isEmpty(idxShard.getReplicaNodeKeyList())) {
            throw new IllegalArgumentException();
        }
        List<String> nodeKeyList = new ArrayList<String>();
        nodeKeyList.add(idxShard.getNodeKey());
        nodeKeyList.addAll(idxShard.getReplicaNodeKeyList());

        Map<String, Node> nodeMap = getNodeMapByNodeKey(clusterName, nodeKeyList, Boolean.TRUE);

        List<Node> resultNodeList = new ArrayList<Node>();
        if (MapUtils.isNotEmpty(nodeMap)) {
            resultNodeList.addAll(nodeMap.values());
        }

        return resultNodeList;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.baidu.rigel.biplatform.tesseract.node.service.ISNodeService#
     * getFreeSearchNodeByIndexShard
     * (com.baidu.rigel.biplatform.tesseract.isservice.meta.IndexShard)
     */
    @Override
    public Node getFreeSearchNodeByIndexShard(IndexShard idxShard, String clusterName) {
        if (idxShard == null || StringUtils.isEmpty(idxShard.getNodeKey())
                && CollectionUtils.isEmpty(idxShard.getReplicaNodeKeyList())) {
            throw new IllegalArgumentException();
        }
        List<Node> currNodeList = getAvailableNodeListByIndexShard(idxShard, clusterName);
        int minRequestCount = 0;
        Node result = null;

        for (int i = 0; i < currNodeList.size(); i++) {
            Node node = currNodeList.get(i);
            if (i == 0) {
                minRequestCount = node.getSearchRequestCount();
            }
            if (node.getSearchRequestCount() <= minRequestCount) {
                minRequestCount = node.getSearchRequestCount();
                result = node;
            }
        }
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#
     * markClusterBadNode(com.baidu.rigel.biplatform.tesseract.node.meta.Node)
     */
    @Override
    public void markClusterBadNode() {
        LOGGER.info(
                String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_BEGIN, "markClusterBadNode", "[no param]"));
        Node currNode = this.getCurrentNode();
        List<Node> nodeList = this.getNodeListByClusterName(currNode.getClusterName());
        if (nodeList != null) {
            for (Node curr : nodeList) {
                long currTime = System.currentTimeMillis();
                if (curr.getNodeState().equals(NodeState.NODE_AVAILABLE)
                        && ((currTime - curr.getLastStateUpdateTime()) > this.nodeStateUpdateMaxIntervalTime)) {
                    curr.setNodeState(NodeState.NODE_UNAVAILABLE);
                    curr.setLastStateUpdateTime(currTime);
                    this.saveOrUpdateNodeInfo(curr);
                    LOGGER.warn(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_PROCESS_NO_PARAM,
                            "markClusterBadNode", "[mark: " + curr.getNodeKey() + " as bad node]"));
                }
            }
        }
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_END, "markClusterBadNode", "[no param]"));
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#saveNodeImage
     * (com.baidu.rigel.biplatform.tesseract.node.meta.Node)
     */
    @Override
    public void saveNodeImage(Node node) {
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_BEGIN, "saveNodeImage",
                "[node:" + node + "]"));
        if (node == null || StringUtils.isEmpty(node.getClusterName())) {
            LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_EXCEPTION, "saveNodeImage",
                    "[node:" + node + "]"));
            throw new IllegalArgumentException();
        }
        FileUtils.write(node.getImageFilePath(), SerializationUtils.serialize(node), true);
        LOGGER.info(
                String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_END, "saveNodeImage", "[node:" + node + "]"));
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#
     * loadLocalNodeImage(com.baidu.rigel.biplatform.tesseract.node.meta.Node)
     */
    @Override
    public Node loadLocalNodeImage(Node node) {
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_BEGIN, "loadLocalNodeImage",
                "[node:" + node + "]"));
        if (node == null || StringUtils.isEmpty(node.getClusterName())) {
            LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_EXCEPTION, "loadLocalNodeImage",
                    "[node:" + node + "]"));
            throw new IllegalArgumentException();
        }
        byte[] nodeInfoByteArr = FileUtils.readFile(node.getImageFilePath());
        Node localNodeInfo = null;
        if (nodeInfoByteArr != null) {
            localNodeInfo = (Node) SerializationUtils.deserialize(nodeInfoByteArr);
            // IP???????
            node.setBlockSize(localNodeInfo.getBlockSize());
            node.setClusterName(localNodeInfo.getClusterName());
            node.setCurrBlockUsed(localNodeInfo.getCurrBlockUsed());
        }

        // ?
        this.saveOrUpdateNodeInfo(node);
        LOGGER.info(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_END, "loadLocalNodeImage",
                "[node:" + node + "]"));
        return node;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.baidu.rigel.biplatform.tesseract.node.service.IsNodeService#
     * getCurrentNode()
     */
    @Override
    public Node getCurrentNode() {
        return this.node;
    }

}