LinkCollUtil.java 8.45 KB
package com.sitech.ismp.coll.link;

import com.sitech.base.AgentProperties;
import com.sitech.ismp.coll.CollBase;
import com.sitech.ismp.coll.basic.TblATO_KPIDETAIL;
import com.sitech.util.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;

import java.io.*;
import java.util.*;

public class LinkCollUtil extends CollBase{
    private Logger logger = Logger.getLogger(LinkCollUtil.class);

    public static String DOWN = "999999";

    private static final long TIME_OUT = 5 * 60 * 1000L;

    private String linkId;
    private String shellName;
    private String resultFile;

    private Date cllTime = new Date();

    private Map<Integer, Hop> hops = new HashMap<Integer, Hop>();

    public Vector<TblATO_KPIDETAIL> getLinkPM(HashMap<String, String> params) {
        init(params);

        // 创建ping脚本文件
        FileUtils.writeFile(LinkCollConst.SCRIPT_PATH, this.shellName, makeShellContent(hops), false);

        // 创建notice文件
        FileUtils.createNewFile(LinkCollConst.NOTICE_PATH, this.shellName);

        // 等待脚本执行结果文件
        File pingResultFile = scanResultFile();

        Map<Integer, Hop> hopMap = parseResultMap(readLine(pingResultFile));

        // 计算链路的时延指标
        calc(hopMap);

        return super.getKPISet();
    }

    /**
     * 读文件
     * @param file
     * @return
     */
    private List<List<String>> readLine(File file) {
        List<List<String>> result = new ArrayList<List<String>>();
        BufferedReader br = null;
        try {
            int i=0;
            br = new BufferedReader(new FileReader(file));
            String line = "";
            while ((line = br.readLine()) != null) {
                if (i >= result.size() || null == result.get(i)) {
                    result.add(i, new ArrayList<String>());
                }
                List<String> elem = result.get(i);

                if (line.trim().equals(LinkCollConst.SPLIT_LINE)) {
                    i++;
                    continue;
                } else if (line.trim().endsWith(LinkCollConst.SPLIT_LINE)) {
                    line = line.replace(LinkCollConst.SPLIT_LINE, "");
                    elem.add(line);
                    i++;
                } else {
                    elem.add(line);
                }
            }

        } catch (Exception e) {
            logger.error("[Link COLL] Exception while readFile:" + file.getAbsolutePath(), e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    logger.error("[Link COLL] IOException:", e);
                }
            }
            file.delete();
        }

        return result;
    }

    /**
     * 获得脚本执行结果文件
     */
    private File scanResultFile() {
        List<List<String>> result = new ArrayList<List<String>>();

        long beginTime = System.currentTimeMillis();
        while(System.currentTimeMillis() - beginTime < TIME_OUT){
            SysHelper.waitIt(this, 1000L);

            File file = new File(LinkCollConst.RESULT_PATH, resultFile);
            if(!file.exists()){
                continue;
            }else{
                SysHelper.waitIt(this, 100L);
                return file;
            }
        }
        if(System.currentTimeMillis() - beginTime >= TIME_OUT){
            logger.error("TIME_OUT");
        }
        return null;
    }

    /**
     * 计算每段链路时延
     * @param hops
     */
    private void calc(Map<Integer, Hop> hops){
        for(Hop hop : hops.values()){
            logger.info(hop.toString());
        }
        // 用于计算链路总时延
        List<String> valueList = new ArrayList<String>();

        for (int i = 0; i < hops.size() - 1; i++) {
            Hop hop = hops.get(i + 1);
            Hop nextHop = hops.get(i + 2);

            String linkDelay;
            String unitId = linkId + ":" + hop.getDevId() + ">" + nextHop.getDevId();
            // 计算每段链路时延
            if (DOWN.equals(hop.getMinTime()) || DOWN.equals(nextHop.getMinTime())) {
                // 若链路两端节点有一个ping不通,则链路为断开
                linkDelay = DOWN;
            } else {
                // 链路时延 = min(pingNextHop) - min(pingHop))
                double d = Double.parseDouble(nextHop.getMinTime()) - Double.parseDouble(hop.getMinTime());
                // 保留3位小数点
                linkDelay = Formater.formatDecimalByScale(String.valueOf(d), 3);
            }

            super.addKPI(unitId, "PM-11-47-01-01", linkDelay, cllTime, null);

            valueList.add(linkDelay);
        } // end for

        calcTotal(valueList);
    }

    /**
     * 用于计算链路总时延
     * @param valueList
     */
    private void calcTotal(List<String> valueList) {
        String kpiValue = "";
        double total = 0d;
        for (String value : valueList) {
            if (DOWN.equals(value)) {
                // 若有一段链路是断开的,则整条链路为断开的
                kpiValue = DOWN;
                break;
            } else {
                total += Double.parseDouble(value);
            }
        }
        if (!DOWN.equals(kpiValue)) {
            kpiValue = Formater.formatDecimalByScale(String.valueOf(total), 3);
        }
        super.addKPI(linkId, "PM-11-47-01-02", kpiValue, cllTime, null);
    }


    /**
     * 解析ping执行结果为Hop对象
     * @param list
     * @return
     */
    private Map<Integer, Hop> parseResultMap(List<List<String>> list){
        Map<Integer, Hop> hopMap = new HashMap<Integer, Hop>();
        for (List<String> elem : list) {
            Hop hop = new Hop(elem);
            hopMap.put(hop.getSeq(), hop);

            if(null != hop.getPacketLoss() && "100".equals(hop.getPacketLoss())){
                hop.setMinTime(DOWN);
                hop.setAvgTime(DOWN);
                hop.setMaxTime(DOWN);
            }
            // ping最小时延
            super.addKPI(linkId + ":" + hop.getDevId(), "PM-11-47-01-03", hop.getMinTime(), cllTime, null);
        }
        return hopMap;
    }


    /**
     * 组装ping脚本内容
     * echo "SEQ=8" >> /rtms/masteragent/result_temp/11-47-040.txt
     * echo "DEVICE_ID=dev1" >> /rtms/masteragent/result_temp/11-47-040.txt
     * ping -c 5 -i 1 172.16.9.233 >> /rtms/masteragent/result_temp/11-47-040.txt
     * echo "*******************************************************************************************#" >> /rtms/masteragent/result_temp/11-47-040.txt
     * @return
     */
    private String makeShellContent(Map<Integer, Hop> hops) {
        StringBuffer sb = new StringBuffer();
        try {
            sb.append(PingHelper.getShellHead()).append("\n");
            for (int i = 0; i < hops.size(); i++) {
                Hop nextHop = hops.get(i + 1);
                sb.append(PingHelper.getSeq(nextHop)).append("\n");
                sb.append(PingHelper.getDevId(nextHop)).append("\n");
                sb.append(PingHelper.getIpAddr(nextHop)).append("\n");
                sb.append(PingHelper.getSplitLine(nextHop)).append("\n");
                sb.append("\n");
            }
            sb.append(PingHelper.getShellFoot(resultFile)).append("\n");

            logger.info("[LINK_" + linkId + " ] Create Ping Shell: \n" + sb.toString());
            return sb.toString();
        } catch (Exception e) {
            throw new RuntimeException("Exception while makeShellContent[" + linkId + "]", e);
        }

    }

    /**
     * 初始化链路参数
     *
     * @param params
     */
    private void init(HashMap<String, String> params) {
        try {
            this.linkId = params.get("LINK_ID");
            this.resultFile = linkId + ".txt";
            this.shellName = "getPing" + linkId + ".sh";

            String json = params.get("JSON_STR");
            logger.info("Coll JsonString : " + json);
            JSONArray arr = (JSONArray) JSONUtil.fromJSON(json);
            if (null == arr || arr.size() < 1) {
                throw new Exception("JSONArray size is 0");
            }
            for (int i = 0; i < arr.size(); i++) {
                JSONObject obj = (JSONObject) arr.get(i);
                Hop nextHop = new Hop(linkId, obj);
                hops.put(nextHop.getSeq(), new Hop(linkId, obj));
            }
        } catch (Exception e) {
            throw new RuntimeException("Exception while init link task:" + JSONUtil.toJSON(params), e);
        }
    }

}