okuyama.imdst.util.DataDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for okuyama.imdst.util.DataDispatcher.java

Source

package okuyama.imdst.util;

import java.util.*;
import java.io.*;
import java.util.concurrent.ConcurrentHashMap;

import okuyama.base.util.ILogger;
import okuyama.base.util.LoggerFactory;
import okuyama.base.lang.BatchException;

import org.apache.commons.codec.digest.DigestUtils;

/**
 * MasterNode??DataNode.<br>
 *
 * @author T.Okuyama
 * @license GPL(Lv3)
 */
public class DataDispatcher {

    public volatile static String rule = null;

    public volatile static int ruleInt = 0;

    public volatile static int[] oldRules = null;

    // ????
    private static ConcurrentHashMap keyNodeMap = new ConcurrentHashMap(6, 6, 512);

    // ConsistentHashCircle
    private static SortedMap nodeCircle = null;

    // ConsistentHashOldCircle
    private static SortedMap oldCircle = null;

    private static HashMap allNodeMap = null;

    private static ArrayList transactionManagerList = null;

    private volatile static boolean standby = false;

    private static Object syncObj = new Object();

    private static int virtualNodeSize = ImdstDefine.consistentHashVirtualNode;

    // ? 0=mod 1=ConsistentHash
    private static int dispatchMode = ImdstDefine.dispatchModeModInt;

    // ????
    private static boolean fixDispatchMode = false;

    // ???????true;
    private static boolean initFlg = false;

    // ?
    // 1?????
    public static void setDispatchMode(String mode) {
        if (!fixDispatchMode) {
            if (mode.equals(ImdstDefine.dispatchModeConsistentHash)) {
                dispatchMode = ImdstDefine.dispatchModeConsistentHashInt;
                fixDispatchMode = true;
            }
        }
    }

    /**
     * ??.<br>
     *
     * @return int 0=mod, 1=ConsistentHash
     */
    public static int getDispatchMode() {
        return dispatchMode;
    }

    /**
     * ?<br>
     * <br>
     * ???.<br>
     * KeyMapNodesRule=(2,9,99,999)<br>
     * KeyMapNodesInfo=Key?(KeyNodeName1:11111, KeyNodeName2:22222)<br>
     * SubKeyMapNodesInfo=Key?(KeyNodeName1:11111, KeyNodeName2:22222)<br>
     * SubKeyMapNodesInfo?????????null<br>
     * ThirdKeyMapNodesInfo=Key?(KeyNodeName1:11111, KeyNodeName2:22222)<br>
     * ThirdKeyMapNodesInfo?????????null<br>
     * SubKeyMapNodesInfo?????ThirdKeyMapNodesInfo????????
     *
     * <br>
     * ??.<br>
     * <br>
     * KeyMapNodesRule:KeyNode?<br>
     *                 ?????????????<br>
     *                 ????5????KeyNode?????10???????10,5??????15??????<br>
     *                 15,10,5???<br>
     * <br>
     * KeyMapNodesInfo:KeyNode(?)IP(??)???":"?????<br>
     * <br>
     * SubKeyMapNodesInfo:???KeyNodeKeyMapNodesInfo????KeyMapNodesInfo????????<br>
     * <br>
     * ThirdKeyMapNodesInfo:???KeyNodeKeyMapNodesInfo????KeyMapNodesInfo????????<br>
     *
     * @param ruleStr 
     * @param oldRules ?
     * @param keyMapNodes 
     * @param subKeyMapNodes 
     * @param thirdKeyMapNodes 
     * @param transactionManagerStr ??
     */
    public static void init(String ruleStr, int[] oldRules, String keyMapNodes, String subKeyMapNodes,
            String thirdKeyMapNodes, String transactionManagerStr) {
        initFlg = true;
        standby = false;
        String[] keyMapNodesInfo = null;
        String[] subkeyMapNodesInfo = null;
        String[] thirdkeyMapNodesInfo = null;
        String[] transactionManagerInfo = null;

        ArrayList keyNodeList = new ArrayList();
        ArrayList subKeyNodeList = new ArrayList();
        ArrayList thirdKeyNodeList = new ArrayList();
        rule = ruleStr.trim();
        ruleInt = new Integer(rule).intValue();

        synchronized (syncObj) {
            allNodeMap = new HashMap();
            // TransactionManager?
            if (transactionManagerStr != null) {
                transactionManagerList = new ArrayList();
                transactionManagerList.add(transactionManagerStr);
            }
        }

        // ???
        // ??
        // [0][*]=Name
        // [1][*]=Port
        // [2][*]=Full
        // [3][*]=Name
        // [4][*]=Port
        // [5][*]=Full
        // [6][*]=Name
        // [7][*]=Port
        // [8][*]=Full
        keyMapNodesInfo = keyMapNodes.split(",");
        String[][] allNodeDetailList = new String[9][keyMapNodesInfo.length];

        // MainNode?
        for (int index = 0; index < keyMapNodesInfo.length; index++) {
            String keyNode = keyMapNodesInfo[index].trim();
            keyNodeList.add(keyNode);

            allNodeDetailList[2][index] = keyNode;

            String[] keyNodeDt = keyNode.split(":");

            allNodeDetailList[0][index] = keyNodeDt[0];
            allNodeDetailList[1][index] = keyNodeDt[1];
        }

        synchronized (syncObj) {
            allNodeMap.put("main", keyNodeList);
        }

        // SubNode?
        if (subKeyMapNodes != null && !subKeyMapNodes.equals("")) {
            subkeyMapNodesInfo = subKeyMapNodes.split(",");

            for (int index = 0; index < subkeyMapNodesInfo.length; index++) {
                String subKeyNode = subkeyMapNodesInfo[index].trim();
                String[] subKeyNodeDt = subKeyNode.split(":");
                subKeyNodeList.add(subKeyNode);

                allNodeDetailList[5][index] = subKeyNode;
                allNodeDetailList[3][index] = subKeyNodeDt[0];
                allNodeDetailList[4][index] = subKeyNodeDt[1];
            }

            synchronized (syncObj) {
                allNodeMap.put("sub", subKeyNodeList);
            }
        }

        // ThirdNode?
        if (thirdKeyMapNodes != null && !thirdKeyMapNodes.equals("")) {
            thirdkeyMapNodesInfo = thirdKeyMapNodes.split(",");

            for (int index = 0; index < thirdkeyMapNodesInfo.length; index++) {
                String thirdKeyNode = thirdkeyMapNodesInfo[index].trim();
                String[] thirdKeyNodeDt = thirdKeyNode.split(":");
                thirdKeyNodeList.add(thirdKeyNode);

                allNodeDetailList[8][index] = thirdKeyNode;
                allNodeDetailList[6][index] = thirdKeyNodeDt[0];
                allNodeDetailList[7][index] = thirdKeyNodeDt[1];
            }

            synchronized (syncObj) {
                allNodeMap.put("third", thirdKeyNodeList);
            }
        }

        DataDispatcher.oldRules = oldRules;
        keyNodeMap.put("list", allNodeDetailList);
        standby = true;
    }

    /**
     * ?<br>
     * ConsistentHash.<br>
     * <br>
     * ???.<br>
     * KeyMapNodesInfo=Key?(KeyNodeName1:11111, KeyNodeName2:22222)<br>
     * SubKeyMapNodesInfo=Key?(KeyNodeName1:11111, KeyNodeName2:22222)<br>
     * SubKeyMapNodesInfo?????????null<br>
     * ThirdKeyMapNodesInfo=Key?(KeyNodeName1:11111, KeyNodeName2:22222)<br>
     * ThirdKeyMapNodesInfo?????????null<br>
     * SubKeyMapNodesInfo?????ThirdKeyMapNodesInfo????????
     * <br>
     * ??.<br>
     * <br>
     * <br>
     * KeyMapNodesInfo:KeyNode(?)IP(??)???":"?????<br>
     * <br>
     * SubKeyMapNodesInfo:???KeyNodeKeyMapNodesInfo????KeyMapNodesInfo????????<br>
     * <br>
     * ThirdKeyMapNodesInfo:???KeyNodeKeyMapNodesInfo????KeyMapNodesInfo????????<br>
     *
     * @param keyMapNodes 
     * @param subKeyMapNodes 
     * @param thirdKeyMapNodes 
     * @param transactionManagerStr ??
     */
    public static void initConsistentHashMode(String keyMapNodes, String subKeyMapNodes, String thirdKeyMapNodes,
            String transactionManagerStr) {
        initFlg = true;
        standby = false;
        String[] keyMapNodesInfo = null;
        String[] subkeyMapNodesInfo = null;
        String[] thirdkeyMapNodesInfo = null;
        String[] transactionManagerInfo = null;

        ArrayList keyNodeList = new ArrayList();
        ArrayList subKeyNodeList = new ArrayList();
        ArrayList thirdKeyNodeList = new ArrayList();

        synchronized (syncObj) {
            allNodeMap = new HashMap();
            // TransactionManager?
            if (transactionManagerStr != null) {
                transactionManagerList = new ArrayList();
                transactionManagerList.add(transactionManagerStr);
            }
        }

        // ???
        // ??
        // [0][*]=Name
        // [1][*]=Port
        // [2][*]=Full
        // [3][*]=Name
        // [4][*]=Port
        // [5][*]=Full
        // [6][*]=Name
        // [7][*]=Port
        // [8][*]=Full
        keyMapNodesInfo = keyMapNodes.split(",");
        String[][] allNodeDetailList = new String[9][keyMapNodesInfo.length];

        // ConsistentHash??
        nodeCircle = new TreeMap();

        // MainNode?
        for (int index = 0; index < keyMapNodesInfo.length; index++) {
            String keyNode = keyMapNodesInfo[index].trim();
            String[] keyNodeDt = keyNode.split(":");
            keyNodeList.add(keyNode);

            allNodeDetailList[2][index] = keyNode;
            allNodeDetailList[0][index] = keyNodeDt[0];
            allNodeDetailList[1][index] = keyNodeDt[1];
            String[] mainNodeDt = { allNodeDetailList[0][index], allNodeDetailList[1][index],
                    allNodeDetailList[2][index] };

            keyNodeMap.put(keyNode, mainNodeDt);

            // ConsistentHash??
            for (int i = 0; i < virtualNodeSize; i++) {

                // FullName???????????Hash??????Circle?
                // KeyNode??
                // ??keyNodeMap?????
                nodeCircle.put(new Integer(sha1Hash4Int(keyNode + "_" + i)), keyNode);
            }
        }

        synchronized (syncObj) {
            allNodeMap.put("main", keyNodeList);
        }

        // SubNode?
        if (subKeyMapNodes != null && !subKeyMapNodes.equals("")) {
            subkeyMapNodesInfo = subKeyMapNodes.split(",");

            for (int index = 0; index < subkeyMapNodesInfo.length; index++) {
                String subKeyNode = subkeyMapNodesInfo[index].trim();
                String[] subKeyNodeDt = subKeyNode.split(":");
                subKeyNodeList.add(subKeyNode);

                allNodeDetailList[5][index] = subKeyNode;
                allNodeDetailList[3][index] = subKeyNodeDt[0];
                allNodeDetailList[4][index] = subKeyNodeDt[1];
                String[] subNodeDt = { allNodeDetailList[3][index], allNodeDetailList[4][index],
                        allNodeDetailList[5][index] };

                keyNodeMap.put(allNodeDetailList[2][index] + "_sub", subNodeDt);
            }

            synchronized (syncObj) {
                allNodeMap.put("sub", subKeyNodeList);
            }
        }

        // ThirdNode?
        if (thirdKeyMapNodes != null && !thirdKeyMapNodes.equals("")) {
            thirdkeyMapNodesInfo = thirdKeyMapNodes.split(",");

            for (int index = 0; index < thirdkeyMapNodesInfo.length; index++) {
                String thirdKeyNode = thirdkeyMapNodesInfo[index].trim();
                String[] thirdKeyNodeDt = thirdKeyNode.split(":");
                thirdKeyNodeList.add(thirdKeyNode);

                allNodeDetailList[8][index] = thirdKeyNode;
                allNodeDetailList[6][index] = thirdKeyNodeDt[0];
                allNodeDetailList[7][index] = thirdKeyNodeDt[1];
                String[] thirdNodeDt = { allNodeDetailList[6][index], allNodeDetailList[7][index],
                        allNodeDetailList[8][index] };

                keyNodeMap.put(allNodeDetailList[2][index] + "_third", thirdNodeDt);
            }

            synchronized (syncObj) {
                allNodeMap.put("third", thirdKeyNodeList);
            }
        }

        keyNodeMap.put("list", allNodeDetailList);
        // 
        standby = true;
    }

    /**
     * ???.<br>
     *
     */
    public static boolean getInitFlg() {
        return initFlg;
    }

    /**
     * ConsitentHash??????.<br>
     * ??????????????????keyNodeMap?<br>
     * "oldNodeCircle"????????.<br>
     * ??????????????Hash??????<br>
     * FullName???HashMap????.<br>
     * ???HashMap?"main"??????"sub"???????"third"?????Map?????.<br>
     * ???"tomain"??????"tosub"??????"tothird"????????.<br>
     *
     * @param keyNodeFullName ? "192.168.1.3:5555"
     * @param subKeyNodeFullName ? "192.168.2.3:5555"
     * @param thirdKeyNodeFullName ? "192.168.2.3:5555"
     * @return HashMap ?
     */
    public static HashMap addNode4ConsistentHash(String keyNodeFullName, String subKeyNodeFullName,
            String thirdKeyNodeFullName) {
        if (oldCircle != null)
            return null;
        HashMap retMap = new HashMap(2);
        HashMap convertMap = new HashMap();
        HashMap subConvertMap = new HashMap();
        HashMap thirdConvertMap = new HashMap();
        ArrayList keyNodeList = new ArrayList();
        ArrayList subKeyNodeList = new ArrayList();
        ArrayList thirdKeyNodeList = new ArrayList();

        oldCircle = new TreeMap();

        // ????
        Set set = nodeCircle.keySet();
        Iterator iterator = set.iterator();

        // oldCircle?
        while (iterator.hasNext()) {
            Integer key = (Integer) iterator.next();
            String nodeFullName = (String) nodeCircle.get(key);
            oldCircle.put(key, nodeFullName);
        }

        // ?
        convertMap = new HashMap();

        for (int i = 0; i < virtualNodeSize; i++) {

            int targetHash = sha1Hash4Int(keyNodeFullName + "_" + i);
            int targetHashStart = 0;
            int targetHashEnd = targetHash;
            String nodeName = null;

            SortedMap headMap = nodeCircle.headMap(targetHash);
            SortedMap tailMap = nodeCircle.tailMap(targetHash);

            // ???????????????
            // ?????1?????????
            // ????????????
            // ????Node01,Node02,Node03???Node04?????
            // Node01?511112430???Node02?45676987654??
            if (headMap.isEmpty()) {

                int hash = ((Integer) nodeCircle.lastKey()).intValue();
                targetHashStart = hash + 1;
                nodeName = (String) nodeCircle.get(nodeCircle.firstKey());
            } else {

                int hash = ((Integer) headMap.lastKey()).intValue();
                targetHashStart = hash + 1;
                if (tailMap.isEmpty()) {

                    nodeName = (String) nodeCircle.get(nodeCircle.firstKey());
                } else {

                    nodeName = (String) nodeCircle.get(tailMap.firstKey());
                }
            }

            // ???????????
            // _??
            // Node01:5553,"6756-9876_12345-987654"
            // Node02:5553,"342-3456_156456-178755"
            if (convertMap.containsKey(nodeName)) {

                String work = (String) convertMap.get(nodeName);
                convertMap.put(nodeName, work + "_" + targetHashStart + "-" + targetHashEnd);

                // 
                String[] subDataNodeInfo = (String[]) keyNodeMap.get(nodeName + "_sub");
                if (subDataNodeInfo != null) {
                    subConvertMap.put(subDataNodeInfo[2], work + "_" + targetHashStart + "-" + targetHashEnd);
                }

                // 
                String[] thirdDataNodeInfo = (String[]) keyNodeMap.get(nodeName + "_third");
                if (thirdDataNodeInfo != null) {
                    thirdConvertMap.put(thirdDataNodeInfo[2], work + "_" + targetHashStart + "-" + targetHashEnd);
                }

            } else {

                convertMap.put(nodeName, targetHashStart + "-" + targetHashEnd);

                // 
                String[] subDataNodeInfo = (String[]) keyNodeMap.get(nodeName + "_sub");
                if (subDataNodeInfo != null) {
                    subConvertMap.put(subDataNodeInfo[2], targetHashStart + "-" + targetHashEnd);
                }

                // 
                String[] thirdDataNodeInfo = (String[]) keyNodeMap.get(nodeName + "_third");
                if (thirdDataNodeInfo != null) {
                    thirdConvertMap.put(thirdDataNodeInfo[2], targetHashStart + "-" + targetHashEnd);
                }

            }
        }

        // ???Map?
        retMap.put("tomain", keyNodeFullName);
        retMap.put("tosub", subKeyNodeFullName);
        retMap.put("tothird", thirdKeyNodeFullName);
        retMap.put("main", convertMap);
        retMap.put("sub", subConvertMap);
        retMap.put("third", thirdConvertMap);

        // ???
        // ??
        // [0][*]=Name
        // [1][*]=Port
        // [2][*]=Full
        // [3][*]=Name
        // [4][*]=Port
        // [5][*]=Full
        // [6][*]=Name
        // [7][*]=Port
        // [8][*]=Full
        String[][] allNodeDetailList = (String[][]) keyNodeMap.get("list");
        String[][] newAllNodeDetailList = new String[9][allNodeDetailList.length + 1];
        keyNodeList = (ArrayList) allNodeMap.get("main");

        // allNodeDetailList??????
        for (int allNodeDetailListIdx = 0; allNodeDetailListIdx < allNodeDetailList[0].length; allNodeDetailListIdx++) {

            newAllNodeDetailList[0][allNodeDetailListIdx] = allNodeDetailList[0][allNodeDetailListIdx];
            newAllNodeDetailList[1][allNodeDetailListIdx] = allNodeDetailList[1][allNodeDetailListIdx];
            newAllNodeDetailList[2][allNodeDetailListIdx] = allNodeDetailList[2][allNodeDetailListIdx];
            newAllNodeDetailList[3][allNodeDetailListIdx] = allNodeDetailList[3][allNodeDetailListIdx];
            newAllNodeDetailList[4][allNodeDetailListIdx] = allNodeDetailList[4][allNodeDetailListIdx];
            newAllNodeDetailList[5][allNodeDetailListIdx] = allNodeDetailList[5][allNodeDetailListIdx];
            newAllNodeDetailList[6][allNodeDetailListIdx] = allNodeDetailList[6][allNodeDetailListIdx];
            newAllNodeDetailList[7][allNodeDetailListIdx] = allNodeDetailList[7][allNodeDetailListIdx];
            newAllNodeDetailList[8][allNodeDetailListIdx] = allNodeDetailList[8][allNodeDetailListIdx];
        }

        String keyNode = keyNodeFullName;
        String[] keyNodeDt = keyNode.split(":");
        keyNodeList.add(keyNode);

        // ??allNodeDetailList?
        newAllNodeDetailList[2][allNodeDetailList.length] = keyNode;
        newAllNodeDetailList[0][allNodeDetailList.length] = keyNodeDt[0];
        newAllNodeDetailList[1][allNodeDetailList.length] = keyNodeDt[1];
        String[] mainNodeDt = { keyNodeDt[0], keyNodeDt[1], keyNode };

        // keyNodeMap?
        keyNodeMap.put(keyNode, mainNodeDt);

        // ConsistentHash??
        for (int i = 0; i < virtualNodeSize; i++) {

            // FullName???????????Hash???Circle?
            // KeyNode??
            // ??keyNodeMap?????
            nodeCircle.put(new Integer(sha1Hash4Int(keyNode + "_" + i)), keyNode);
        }

        synchronized (syncObj) {
            allNodeMap.put("main", keyNodeList);
        }

        // SubNode?
        if (subKeyNodeFullName != null && !subKeyNodeFullName.equals("")) {
            String subKeyNode = subKeyNodeFullName;
            String[] subKeyNodeDt = subKeyNode.split(":");
            subKeyNodeList = (ArrayList) allNodeMap.put("sub", subKeyNodeList);

            subKeyNodeList.add(subKeyNode);

            newAllNodeDetailList[5][allNodeDetailList.length] = subKeyNode;
            newAllNodeDetailList[3][allNodeDetailList.length] = subKeyNodeDt[0];
            newAllNodeDetailList[4][allNodeDetailList.length] = subKeyNodeDt[1];
            String[] subNodeDt = { subKeyNodeDt[0], subKeyNodeDt[1], subKeyNode };

            keyNodeMap.put(newAllNodeDetailList[2][allNodeDetailList.length] + "_sub", subNodeDt);

            synchronized (syncObj) {
                allNodeMap.put("sub", subKeyNodeList);
            }
        }

        // ThirdNode?
        if (thirdKeyNodeFullName != null && !thirdKeyNodeFullName.equals("")) {
            String thirdKeyNode = thirdKeyNodeFullName;
            String[] thirdKeyNodeDt = thirdKeyNode.split(":");
            thirdKeyNodeList = (ArrayList) allNodeMap.put("third", thirdKeyNodeList);

            thirdKeyNodeList.add(thirdKeyNode);

            newAllNodeDetailList[8][allNodeDetailList.length] = thirdKeyNode;
            newAllNodeDetailList[6][allNodeDetailList.length] = thirdKeyNodeDt[0];
            newAllNodeDetailList[7][allNodeDetailList.length] = thirdKeyNodeDt[1];
            String[] thirdNodeDt = { thirdKeyNodeDt[0], thirdKeyNodeDt[1], thirdKeyNode };

            keyNodeMap.put(newAllNodeDetailList[2][allNodeDetailList.length] + "_third", thirdNodeDt);

            synchronized (syncObj) {
                allNodeMap.put("third", thirdKeyNodeList);
            }
        }

        // ????
        keyNodeMap.put("list", newAllNodeDetailList);

        return retMap;
    }

    /**
     * ?????.<br>
     *
     */
    public static void clearConsistentHashOldCircle() {
        if (oldCircle != null) {
            oldCircle = null;
        }
    }

    /**
     * ??.<br>
     *
     * @return int[] ?
     */
    public static int[] getOldRules() {
        return oldRules;
    }

    /**
     * Rule?????????KeyNode?????????.<br>
     * ????????????????6?Third????9??<br>
     * ??Mod or ConsistentHash<br>
     * [Mod]<br>
     * ?????<br>
     * hash % ? = ?<br>
     * <br>
     * [ConsistentHash]<br>
     * ConsistentHash?????.<br>
     *
     * @param key 
     * @param reverse 
     * @return String ?(??????)
     */
    public static String[] dispatchKeyNode(String key, boolean reverse) {
        String[] ret = null;
        if (dispatchMode == 0) {

            // mod
            ret = dispatchModKeyNode(key, false);
        } else if (dispatchMode == 1) {

            // Consistent Hash
            ret = dispatchConsistentHashKeyNode(key, false);
        }

        return adjustmentAccessNode(ret, reverse);
    }

    /**
     * Rule?????????KeyNode?????????.<br>
     * ????????????????6?Third????9??<br>
     * ??Mod or ConsistentHash<br>
     * ??????????.<br>
     * Mod????????????????????<br>
     *
     *
     * [Mod]<br>
     * ?????<br>
     * hash % ? = ?<br>
     * <br>
     * [ConsistentHash]<br>
     * ConsistentHash?????.<br>
     *
     * @param key 
     * @param reverse 
     * @param useRule 
     * @return String[] ?(??????)
     */
    public static String[] dispatchKeyNode(String key, boolean reverse, int useRule) {

        String[] ret = null;
        if (dispatchMode == 0) {

            // mod
            if (oldRules != null && oldRules.length > useRule)
                ret = dispatchModKeyNode(key, false, oldRules[useRule]);
        } else if (dispatchMode == 1) {

            // Consistent Hash
            if (useRule == 0 && oldCircle != null)
                ret = dispatchConsistentHashKeyNode(key, false, true);
        }
        return adjustmentAccessNode(ret, reverse);
    }

    /**
     * DataNode???????.<br>
     * ??????.<br>
     *
     * @param nodes
     * @param reverse
     * @return String[]
     */
    private static String[] adjustmentAccessNode(String[] nodes, boolean reverse) {
        String[] retNodes = null;

        if (nodes == null) {

            return nodes;
        } else if (nodes.length == 3) {

            return nodes;
        } else if (nodes.length == 6) {

            // MainDataNode????Sub????
            if (!StatusUtil.isNodeArrival(nodes[2]) && StatusUtil.isNodeArrival(nodes[5])) {
                retNodes = new String[6];
                retNodes[0] = nodes[3];
                retNodes[1] = nodes[4];
                retNodes[2] = nodes[5];
                retNodes[3] = nodes[0];
                retNodes[4] = nodes[1];
                retNodes[5] = nodes[2];
            } else {

                if (reverse) {

                    // SubNode??????
                    retNodes = new String[6];
                    retNodes[3] = nodes[0];
                    retNodes[4] = nodes[1];
                    retNodes[5] = nodes[2];

                    retNodes[0] = nodes[3];
                    retNodes[1] = nodes[4];
                    retNodes[2] = nodes[5];
                } else {
                    retNodes = nodes;
                }
            }
        } else if (nodes.length == 9) {

            // Main?SubDataNode????Third????
            if (!StatusUtil.isNodeArrival(nodes[2]) && !StatusUtil.isNodeArrival(nodes[5])) {
                retNodes = new String[9];
                retNodes[0] = nodes[6];
                retNodes[1] = nodes[7];
                retNodes[2] = nodes[8];
                retNodes[3] = nodes[0];
                retNodes[4] = nodes[1];
                retNodes[5] = nodes[2];
                retNodes[6] = nodes[3];
                retNodes[7] = nodes[4];
                retNodes[8] = nodes[5];
            } else if (!StatusUtil.isNodeArrival(nodes[2]) && StatusUtil.isNodeArrival(nodes[5])) {

                if (reverse == true) {
                    // MainDataNode???Sub?Third?????reverse???????
                    retNodes = new String[9];
                    retNodes[0] = nodes[6];
                    retNodes[1] = nodes[7];
                    retNodes[2] = nodes[8];
                    retNodes[3] = nodes[3];
                    retNodes[4] = nodes[4];
                    retNodes[5] = nodes[5];
                    retNodes[6] = nodes[0];
                    retNodes[7] = nodes[1];
                    retNodes[8] = nodes[2];
                } else {
                    retNodes = new String[9];
                    retNodes[0] = nodes[3];
                    retNodes[1] = nodes[4];
                    retNodes[2] = nodes[5];
                    retNodes[3] = nodes[6];
                    retNodes[4] = nodes[7];
                    retNodes[5] = nodes[8];
                    retNodes[6] = nodes[0];
                    retNodes[7] = nodes[1];
                    retNodes[8] = nodes[2];
                }
            } else if (StatusUtil.isNodeArrival(nodes[2]) && !StatusUtil.isNodeArrival(nodes[5])) {
                if (reverse == true) {
                    // SubDataNode???Main?Third?????reverse???????
                    retNodes = new String[9];
                    retNodes[0] = nodes[6];
                    retNodes[1] = nodes[7];
                    retNodes[2] = nodes[8];
                    retNodes[3] = nodes[0];
                    retNodes[4] = nodes[1];
                    retNodes[5] = nodes[2];
                    retNodes[6] = nodes[3];
                    retNodes[7] = nodes[4];
                    retNodes[8] = nodes[5];
                } else {
                    retNodes = new String[9];
                    retNodes[0] = nodes[0];
                    retNodes[1] = nodes[1];
                    retNodes[2] = nodes[2];
                    retNodes[3] = nodes[6];
                    retNodes[4] = nodes[7];
                    retNodes[5] = nodes[8];
                    retNodes[6] = nodes[3];
                    retNodes[7] = nodes[4];
                    retNodes[8] = nodes[5];
                }
            } else {
                retNodes = nodes;
            }
        }
        return retNodes;
    }

    /**
     * Rule?????????KeyNode?????????.<br>
     * Mod.<br>
     * ?KeyNode??????KeyNode???<br>
     * ????????????<br>
     * MainNode?SubNode???????????????.<br>
     *
     * @param key 
     * @param reverse 
     * @return String ?(??????)
     */
    private static String[] dispatchModKeyNode(String key, boolean reverse) {
        return dispatchModKeyNode(key, reverse, ruleInt);
    }

    /**
     * Rule?????????KeyNode?????????.<br>
     * Mod.<br>
     * ?KeyNode??????KeyNode???<br>
     * ????????????<br>
     * MainNode?SubNode???????????????.<br>
     *
     * @param key 
     * @param reverse 
     * @param useRule 
     * @return String ?(??????)
     */
    private static String[] dispatchModKeyNode(String key, boolean reverse, int useRule) {
        String[] ret = null;
        String[] tmp = decisionModKeyNode(key, useRule);

        if (reverse) {
            // SubNode??????
            if (tmp.length > 6) {
                ret = new String[9];
                ret[3] = tmp[0];
                ret[4] = tmp[1];
                ret[5] = tmp[2];

                ret[0] = tmp[3];
                ret[1] = tmp[4];
                ret[2] = tmp[5];

                ret[6] = tmp[6];
                ret[7] = tmp[7];
                ret[8] = tmp[8];
            } else if (tmp.length > 3) {
                ret = new String[6];
                ret[3] = tmp[0];
                ret[4] = tmp[1];
                ret[5] = tmp[2];

                ret[0] = tmp[3];
                ret[1] = tmp[4];
                ret[2] = tmp[5];
            } else {
                ret = tmp;
            }

        } else {
            ret = tmp;
        }
        return ret;
    }

    /**
     * Rule?????????KeyNode?????????.<br>
     * Mod.<br>
     * ????????????????6?Third????9??<br>
     * ?????.<br>
     * hash % ? = ?.<br>
     *
     * @param key 
     * @param useRule 
     * @return String[] ?(??????)
     */
    private static String[] decisionModKeyNode(String key, int useRule) {
        String[] ret = null;
        boolean noWaitFlg = false;

        // ??
        String[][] allNodeDetailList = (String[][]) keyNodeMap.get("list");

        // Key?Hash?
        int execKeyInt = key.hashCode();

        if (execKeyInt < 0) {
            execKeyInt = execKeyInt - execKeyInt - execKeyInt;
        }

        int nodeNo = execKeyInt % useRule;

        if (nodeNo == 0) {
            nodeNo = useRule;
        }

        nodeNo = nodeNo - 1;

        // ????????
        if (allNodeDetailList[6][0] != null) {
            // 
            ret = new String[9];

            ret[3] = allNodeDetailList[3][nodeNo];
            ret[4] = allNodeDetailList[4][nodeNo];
            ret[5] = allNodeDetailList[5][nodeNo];

            ret[6] = allNodeDetailList[6][nodeNo];
            ret[7] = allNodeDetailList[7][nodeNo];
            ret[8] = allNodeDetailList[8][nodeNo];
        } else if (allNodeDetailList[3][0] != null) {
            // ????????
            ret = new String[6];

            ret[3] = allNodeDetailList[3][nodeNo];
            ret[4] = allNodeDetailList[4][nodeNo];
            ret[5] = allNodeDetailList[5][nodeNo];
        } else {
            ret = new String[3];
        }

        ret[0] = allNodeDetailList[0][nodeNo];
        ret[1] = allNodeDetailList[1][nodeNo];
        ret[2] = allNodeDetailList[2][nodeNo];

        // ??????????(???)
        // ????????Wait
        while (true) {
            noWaitFlg = false;
            // ????
            if (ret.length == 3) {
                if (!StatusUtil.isWaitStatus(allNodeDetailList[2][nodeNo]))
                    noWaitFlg = true;
            }

            if (ret.length == 6) {
                if (!StatusUtil.isWaitStatus(allNodeDetailList[2][nodeNo])
                        && !StatusUtil.isWaitStatus(allNodeDetailList[5][nodeNo])) {

                    noWaitFlg = true;
                }
            }

            if (ret.length == 9) {
                if (!StatusUtil.isWaitStatus(allNodeDetailList[2][nodeNo])
                        && !StatusUtil.isWaitStatus(allNodeDetailList[5][nodeNo])
                        && !StatusUtil.isWaitStatus(allNodeDetailList[8][nodeNo])) {

                    noWaitFlg = true;
                }
            }

            if (noWaitFlg)
                break;

            try {
                //System.out.println("DataDispatcher - ?");
                Thread.sleep(50);
            } catch (Exception e) {
            }
        }

        // ??
        // ?MasterManagerHelper??
        StatusUtil.addNodeUse(allNodeDetailList[2][nodeNo]);

        if (ret.length > 3) {
            StatusUtil.addNodeUse(allNodeDetailList[5][nodeNo]);
        }

        if (ret.length > 6) {
            StatusUtil.addNodeUse(allNodeDetailList[8][nodeNo]);
        }

        return ret;
    }

    /**
     * Rule?????????KeyNode?????????.<br>
     * ConsistentHash.<br>
     * ????????????????6?Third????9??<br>
     *
     * @param key 
     * @param reverse 
     * @return String[] ?(??????)
     */
    private static String[] dispatchConsistentHashKeyNode(String key, boolean reverse) {
        return dispatchConsistentHashKeyNode(key, reverse, false);
    }

    /**
     * Rule?????????KeyNode?????????.<br>
     * ConsistentHash.<br>
     * ????????????????6?Third????9??<br>
     *
     * @param key 
     * @param reverse 
     * @param useOldCircle 
     * @return String ?(??????)
     */
    private static String[] dispatchConsistentHashKeyNode(String key, boolean reverse, boolean useOldCircle) {
        String[] ret = null;
        String[] tmp = decisionConsistentHashKeyNode(key, useOldCircle);

        if (reverse) {
            // SubNode??????
            if (tmp.length > 6) {
                ret = new String[9];
                ret[3] = tmp[0];
                ret[4] = tmp[1];
                ret[5] = tmp[2];

                ret[0] = tmp[3];
                ret[1] = tmp[4];
                ret[2] = tmp[5];

                ret[6] = tmp[6];
                ret[7] = tmp[7];
                ret[8] = tmp[8];

            } else if (tmp.length > 3) {
                ret = new String[6];
                ret[3] = tmp[0];
                ret[4] = tmp[1];
                ret[5] = tmp[2];

                ret[0] = tmp[3];
                ret[1] = tmp[4];
                ret[2] = tmp[5];
            } else {
                ret = tmp;
            }

        } else {
            ret = tmp;
        }
        return ret;
    }

    /**
     * Rule?????????KeyNode?????????.<br>
     * ConsistentHash.<br>
     * ????????????????6?Third????9??<br>
     *
     * @param key 
     * @param useOldCircle 
     * @return String[] ?(??????)
     */
    private static String[] decisionConsistentHashKeyNode(String key, boolean useOldCircle) {
        String[] ret = null;
        boolean noWaitFlg = false;
        SortedMap useNodeCircle = null;
        String targetNode = null;
        String[] mainDataNodeInfo = null;
        String[] slaveDataNodeInfo = null;
        String[] thirdDataNodeInfo = null;

        // ??
        String[][] allNodeDetailList = (String[][]) keyNodeMap.get("list");

        // Key?Hash?
        int execKeyInt = sha1Hash4Int(key);

        // ??
        // useOldCircle???????
        if (useOldCircle && oldCircle != null) {
            useNodeCircle = oldCircle;
        } else {
            useNodeCircle = nodeCircle;
        }

        // ?
        int hash = sha1Hash4Int(key);

        if (!useNodeCircle.containsKey(hash)) {
            SortedMap<Integer, Map> tailMap = useNodeCircle.tailMap(hash);
            if (tailMap.isEmpty()) {
                hash = ((Integer) useNodeCircle.firstKey()).intValue();
            } else {
                hash = ((Integer) tailMap.firstKey()).intValue();
            }
        }

        // ???
        targetNode = (String) useNodeCircle.get(hash);

        // ??
        mainDataNodeInfo = (String[]) keyNodeMap.get(targetNode);
        // ??
        slaveDataNodeInfo = (String[]) keyNodeMap.get(targetNode + "_sub");
        // ??
        thirdDataNodeInfo = (String[]) keyNodeMap.get(targetNode + "_third");

        // ????????
        if (thirdDataNodeInfo != null) {
            ret = new String[9];

            ret[3] = slaveDataNodeInfo[0];
            ret[4] = slaveDataNodeInfo[1];
            ret[5] = slaveDataNodeInfo[2];
            ret[6] = thirdDataNodeInfo[0];
            ret[7] = thirdDataNodeInfo[1];
            ret[8] = thirdDataNodeInfo[2];

        } else if (slaveDataNodeInfo != null) {
            // ????????
            ret = new String[6];

            ret[3] = slaveDataNodeInfo[0];
            ret[4] = slaveDataNodeInfo[1];
            ret[5] = slaveDataNodeInfo[2];
        } else {
            ret = new String[3];
        }

        ret[0] = mainDataNodeInfo[0];
        ret[1] = mainDataNodeInfo[1];
        ret[2] = mainDataNodeInfo[2];

        // ??????????(???)
        // ????????Wait
        while (true) {
            noWaitFlg = false;
            // ????
            if (ret.length == 3) {
                if (!StatusUtil.isWaitStatus(mainDataNodeInfo[2]))
                    noWaitFlg = true;
            }

            if (ret.length == 6) {
                if (!StatusUtil.isWaitStatus(mainDataNodeInfo[2])
                        && !StatusUtil.isWaitStatus(slaveDataNodeInfo[2])) {

                    noWaitFlg = true;
                }
            }

            if (ret.length == 9) {
                if (!StatusUtil.isWaitStatus(mainDataNodeInfo[2]) && !StatusUtil.isWaitStatus(slaveDataNodeInfo[2])
                        && !StatusUtil.isWaitStatus(thirdDataNodeInfo[2])) {

                    noWaitFlg = true;
                }
            }

            if (noWaitFlg)
                break;

            try {
                //System.out.println("DataDispatcher - ?");
                Thread.sleep(50);
            } catch (Exception e) {
            }
        }

        // ??
        // ?MasterManagerHelper??
        StatusUtil.addNodeUse(mainDataNodeInfo[2]);

        if (ret.length > 3) {
            StatusUtil.addNodeUse(slaveDataNodeInfo[2]);
        }

        if (ret.length > 6) {
            StatusUtil.addNodeUse(thirdDataNodeInfo[2]);
        }

        return ret;
    }

    /**
     * ?Key?????matchNo?????.<br>
     *
     * @param key ?
     * @param rule 
     * @param matchNo No
     * @return boolean ?
     */
    public static boolean isRuleMatchKey(String key, int rule, int matchNo) {
        boolean ret = false;

        // Key?Hash?
        int execKeyInt = key.hashCode();

        if (execKeyInt < 0)
            execKeyInt = execKeyInt - execKeyInt - execKeyInt;

        int targetNo = execKeyInt % rule;

        if (targetNo == 0) {
            targetNo = rule;
        }

        targetNo = targetNo - 1;

        if (targetNo == matchNo)
            ret = true;

        return ret;
    }

    /**
     * ?Key?????????.<br>
     *
     * @param key ?
     * @param rangs 
     * @return boolean ?
     */
    public static boolean isRangeData(String key, int[][] rangs) {
        boolean ret = false;
        //System.out.println(rangs.length);
        //System.out.println(rangs[0].length);
        // 
        for (int rangsIdx = 0; rangsIdx < rangs.length; rangsIdx++) {
            //System.out.println(rangs[rangsIdx][0] + "-" +  rangs[rangsIdx][1]);
            //  start < end??
            if (rangs[rangsIdx][0] < rangs[rangsIdx][1]) {

                if (rangs[rangsIdx][0] <= sha1Hash4Int(key) && sha1Hash4Int(key) <= rangs[rangsIdx][1]) {

                    // 
                    ret = true;
                    break;
                }
            } else {

                // ? ?????????
                //  start > end??
                if (rangs[rangsIdx][0] <= sha1Hash4Int(key)) {

                    // 
                    ret = true;
                    break;
                } else if (rangs[rangsIdx][1] >= sha1Hash4Int(key)) {

                    // 
                    ret = true;
                    break;
                }
            }
        }

        return ret;
    }

    /**
     * ????.<br>
     * ?????Map??"main"?"sub"?"third"???Key?????ArrayList?<br>
     * ??????":"?????????.<br>
     * "sub"?????????????<br>
     * "third"?????????????<br>
     *sub?????third????????
     *
     * @return 
     */
    public static HashMap getAllDataNodeInfo() {
        while (!standby) {
            try {
                Thread.sleep(50);
            } catch (Exception e) {
            }
        }

        HashMap retMap = null;
        ArrayList mainNodeList = new ArrayList();
        ArrayList subNodeList = new ArrayList();
        ArrayList thirdNodeList = new ArrayList();

        // ???
        synchronized (syncObj) {

            retMap = new HashMap(2);

            ArrayList tmpNodeList = (ArrayList) allNodeMap.get("main");

            for (int i = 0; i < tmpNodeList.size(); i++) {
                mainNodeList.add(tmpNodeList.get(i));
            }
            retMap.put("main", mainNodeList);

            // 
            if (allNodeMap.containsKey("sub")) {
                tmpNodeList = (ArrayList) allNodeMap.get("sub");

                for (int i = 0; i < tmpNodeList.size(); i++) {
                    subNodeList.add(tmpNodeList.get(i));
                }
                retMap.put("sub", subNodeList);
            }

            // 
            if (allNodeMap.containsKey("third")) {
                tmpNodeList = (ArrayList) allNodeMap.get("third");

                for (int i = 0; i < tmpNodeList.size(); i++) {
                    thirdNodeList.add(tmpNodeList.get(i));
                }
                retMap.put("third", thirdNodeList);
            }

        }
        return retMap;
    }

    /**
     * TransactionManager??.<br>
     *
     */
    public static ArrayList getTransactionManagerInfo() {
        while (!standby) {
            try {
                Thread.sleep(50);
            } catch (Exception e) {
            }
        }

        ArrayList retList = null;

        // ???
        synchronized (syncObj) {
            if (transactionManagerList != null)
                retList = (ArrayList) transactionManagerList.clone();
        }
        return retList;
    }

    /**
     * sha1??Hash??java?hashCode???.<br>
     * ????<br>
     *
     * @param targete
     * @param int
     */
    public static int sha1Hash4Int(String target) {
        int ret = new String(DigestUtils.sha(target.getBytes())).hashCode();
        if (ret < 0) {
            ret = ret - ret - ret;
        }
        return ret;
    }

    /**
     * ??
     * @return boolean
     */
    public static boolean hasOldRule() {
        boolean ret = false;

        if (dispatchMode == ImdstDefine.dispatchModeModInt) {
            if (oldRules != null)
                ret = true;
        } else if (dispatchMode == ImdstDefine.dispatchModeConsistentHashInt) {
            if (oldCircle != null)
                ret = true;
        }
        return ret;
    }

    /**
     * ?????????????.<br>
     *
     * @return boolean 
     */
    public static boolean isStandby() {
        while (!standby) {
            try {
                Thread.sleep(50);
            } catch (Exception e) {
            }
        }
        return standby;
    }
}