package com.dy.aceMw.resource.rtuLog; 
 | 
  
 | 
import java.io.BufferedWriter; 
 | 
import java.io.File; 
 | 
import java.io.FileInputStream; 
 | 
import java.io.FileOutputStream; 
 | 
import java.io.IOException; 
 | 
import java.io.OutputStreamWriter; 
 | 
  
 | 
import com.dy.aceMw.resource.ResourceUnit; 
 | 
import org.apache.logging.log4j.LogManager; 
 | 
import org.apache.logging.log4j.Logger; 
 | 
  
 | 
import com.dy.common.util.DateTime; 
 | 
import com.dy.common.queue.Queue; 
 | 
import com.dy.common.threadPool.ThreadPool; 
 | 
import com.dy.common.threadPool.TreadPoolFactory; 
 | 
  
 | 
public class RtuLogManager { 
 | 
     
 | 
    private static final Logger log = LogManager.getLogger(RtuLogManager.class) ; 
 | 
     
 | 
    private static final RtuLogManager instance = new RtuLogManager() ; 
 | 
     
 | 
    private static final Queue logQueue = new Queue("rtuLogQueue") ; 
 | 
     
 | 
    private static final Integer maxNodeAddWorkThread = 500 ;//缓存达到这个数量,将增加线程  
 | 
    private static final Integer maxWorkThread = 5 ;//最大工作线程数 
 | 
    private static final Object maxWorkThreadSynObj = new Object() ;//最大工作线程数 
 | 
    private static int workThread = 0 ;//工作线程数 
 | 
     
 | 
    private RtuLogManager(){ 
 | 
    } 
 | 
    @SuppressWarnings("unused") 
 | 
    public static RtuLogManager getInstance(){ 
 | 
        return instance ; 
 | 
    } 
 | 
     
 | 
    /** 
 | 
     * 设置队列限制 
 | 
     * @param warnSize 队列节点数量 报警值 
 | 
     * @param maxSize 队列节点数量 最大值 
 | 
     */ 
 | 
    @SuppressWarnings("unused") 
 | 
    public void setQueueLimit(int warnSize, int maxSize){ 
 | 
        logQueue.setLimit(warnSize, maxSize); 
 | 
    } 
 | 
     
 | 
    /** 
 | 
     * 加入Rtu日志数据 
 | 
     * 在单线程中执行 
 | 
     * @param logNodeObj 日志队列节点对象 
 | 
     * @throws Exception 异常 
 | 
     */ 
 | 
    public void pushRtuLog(RtuLogNode logNodeObj) throws Exception{ 
 | 
        logQueue.pushTail(logNodeObj); 
 | 
        //在单线程中执行 
 | 
        if(workThread <= 0){ 
 | 
            startWorkThread() ; 
 | 
        } 
 | 
    } 
 | 
     
 | 
    /** 
 | 
     * 启动工作线程工作 
 | 
     */ 
 | 
    private void startWorkThread(){ 
 | 
        workThread ++  ; 
 | 
        try { 
 | 
            TreadPoolFactory.getThreadPoolShort().putJob(new ThreadPool.Job() { 
 | 
                public void execute() { 
 | 
                    while(logQueue.size() > 0){ 
 | 
                        RtuLogNode node ; 
 | 
                        if(workThread > 1){ 
 | 
                            synchronized(logQueue){ 
 | 
                                node = (RtuLogNode)logQueue.pop() ; 
 | 
                            } 
 | 
                        }else{ 
 | 
                            node = (RtuLogNode)logQueue.pop() ; 
 | 
                        } 
 | 
                        if(node != null){ 
 | 
                            //日志文件存储 
 | 
                            log(node.rtuAddr, node.content) ; 
 | 
                        } 
 | 
                         
 | 
                        if(RtuLogManager.logQueue.size() > maxNodeAddWorkThread){ 
 | 
                            if(workThread < maxWorkThread){ 
 | 
                                synchronized(maxWorkThreadSynObj){ 
 | 
                                    if(workThread < maxWorkThread){ 
 | 
                                        startWorkThread() ; 
 | 
                                    } 
 | 
                                } 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                    workThread --  ; 
 | 
                    if(workThread < 0){ 
 | 
                        workThread = 0 ; 
 | 
                    } 
 | 
                } 
 | 
                 
 | 
                             
 | 
                /* 
 | 
                 * 强制停止execute方法中执行的死循环工作 
 | 
                 */ 
 | 
                @Override 
 | 
                public void destroy() { 
 | 
                    //再将启动,防止无线程处理了 
 | 
                    startWorkThread() ; 
 | 
                } 
 | 
  
 | 
                /** 
 | 
                 * execute方法中调用此方法判断是否结束死循环工作 
 | 
                 */ 
 | 
                @Override 
 | 
                public boolean isDestroy() { 
 | 
                    return false; 
 | 
                } 
 | 
            }) ; 
 | 
        }catch(Exception e){ 
 | 
            log.error(e); 
 | 
            workThread -- ; 
 | 
            if(workThread < 0){ 
 | 
                workThread = 0 ; 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
     
 | 
    /** 
 | 
     * 记录Rtu日志 
 | 
     * @param rtuAddr 控制器地址 
 | 
     * @param conent 日志内容 
 | 
     */ 
 | 
    private void log(String rtuAddr , String conent){ 
 | 
        File f = getFileForWrite(ResourceUnit.confVo.rtuLogDir , rtuAddr.trim()) ; 
 | 
        if(f != null){ 
 | 
            writeLog(f , DateTime.yyyy_MM_dd_HH_mm_ss() + "  " + conent) ; 
 | 
        }else{ 
 | 
            log.error("不能得到地址为:" + rtuAddr + "的Rtu日志文件!") ; 
 | 
        } 
 | 
    } 
 | 
     
 | 
    /** 
 | 
     * 得到日志文件 
 | 
     * @param path 文件路径 
 | 
     * @param rtuAddr 控制器地址 
 | 
     * @return 日志文件 
 | 
     */ 
 | 
    private File getFileForWrite(String path , String rtuAddr) { 
 | 
        File dir = new File(path) ; 
 | 
        if(!dir.exists()){ 
 | 
            if(!dir.mkdirs()){ 
 | 
                return null ; 
 | 
            } 
 | 
        } 
 | 
        File f = new File(path + rtuAddr + ".log"); 
 | 
        FileInputStream in = null; 
 | 
        try { 
 | 
            if (f.exists()) { 
 | 
                in = new FileInputStream(f); 
 | 
                if(in.available() >= ResourceUnit.confVo.rtuLogFileMaxSize){ 
 | 
                    in.close() ;//必须加上此语句 
 | 
                    File oldestLog = new File(path + rtuAddr + ".log." + (ResourceUnit.confVo.rtuLogFileMaxCount - 1)) ; 
 | 
                    if(oldestLog.exists()){ 
 | 
                        if(!oldestLog.delete()){ 
 | 
                            return null ; 
 | 
                        } 
 | 
                    } 
 | 
                    for(int i = (ResourceUnit.confVo.rtuLogFileMaxCount - 2) ; i > 0  ; i--){ 
 | 
                        File oldLog = new File(path + rtuAddr + ".log." + i) ; 
 | 
                        if(oldLog.exists()){ 
 | 
                            if(!oldLog.renameTo(new File(path + rtuAddr + ".log." + (i + 1)))){ 
 | 
                                return null ; 
 | 
                            } 
 | 
                            if(!oldLog.delete()){ 
 | 
                                return null ; 
 | 
                            } 
 | 
                        } 
 | 
                    } 
 | 
                    if(!f.renameTo(new File(path + rtuAddr + ".log." + 1))){ 
 | 
                        return null ; 
 | 
                    } 
 | 
                    if(!f.delete()){ 
 | 
                        return null ; 
 | 
                    } 
 | 
  
 | 
                    f = new File(path + rtuAddr + ".log"); 
 | 
                    if(!f.exists()){ 
 | 
                        if(f.createNewFile()){ 
 | 
                            return f ; 
 | 
                        }else{ 
 | 
                            return null ; 
 | 
                        } 
 | 
                    } 
 | 
                }else{ 
 | 
                    return f ; 
 | 
                } 
 | 
            }else{ 
 | 
                if(f.createNewFile()){ 
 | 
                    return f ; 
 | 
                }else{ 
 | 
                    return null ; 
 | 
                } 
 | 
            } 
 | 
        } catch (Exception e) { 
 | 
            log.error("得到Rtu(" + rtuAddr + ")日志文件时出错" , e) ; 
 | 
        }finally{ 
 | 
            try { 
 | 
                if (in != null) { 
 | 
                    in.close(); 
 | 
                } 
 | 
            } catch (IOException e) { 
 | 
                log.error("关闭Rtu日志文件(" + f.getName() + ")读入流时出错" , e) ; 
 | 
            } 
 | 
        } 
 | 
        return null; 
 | 
    } 
 | 
     
 | 
    /** 
 | 
     * 向文件中写入日志 
 | 
     * @param f 文件 
 | 
     * @param conent 日志内容 
 | 
     */ 
 | 
    private void writeLog(File f, String conent) { 
 | 
        if (f.exists()) { 
 | 
            BufferedWriter out = null; 
 | 
            try { 
 | 
                out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f, true))); // 参数为true,表示追加内容 
 | 
                out.write(conent + "\n"); 
 | 
            } catch (Exception e) { 
 | 
                log.error("写入Rtu日志文件(" + f.getName() + ")时出错" , e) ; 
 | 
            } finally { 
 | 
                try { 
 | 
                    if (out != null) { 
 | 
                        out.close(); 
 | 
                    } 
 | 
                } catch (IOException e) { 
 | 
                    log.error("关闭Rtu日志文件(" + f.getName() + ")写出流时出错" , e) ; 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
     
 | 
} 
 |