New file |
| | |
| | | package com.dy.rtuMw.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.rtuMw.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 content 日志内容 |
| | | */ |
| | | private void log(String rtuAddr , String content){ |
| | | Object[] res = getFileForWrite(ResourceUnit.confVo.rtuLogDir , rtuAddr.trim()) ; |
| | | if(res[0] != null){ |
| | | writeLog((File)res[0] , DateTime.yyyy_MM_dd_HH_mm_ss() + " " + content) ; |
| | | }else{ |
| | | log.error("不能得到地址为:" + rtuAddr + "的Rtu日志文件!(信息编码" + res[1] + ")") ; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 得到日志文件 |
| | | * @param path 文件路径 |
| | | * @param rtuAddr 控制器地址 |
| | | * @return 日志文件 |
| | | */ |
| | | private Object[] getFileForWrite(String path , String rtuAddr) { |
| | | File dir = new File(path) ; |
| | | if(!dir.exists()){ |
| | | if(!dir.mkdirs()){ |
| | | return new Object[]{null, 1} ; |
| | | } |
| | | } |
| | | 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 new Object[]{null, 2} ; |
| | | } |
| | | } |
| | | 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 new Object[]{null, 3} ; |
| | | } |
| | | if(!oldLog.delete()){ |
| | | return new Object[]{null, 4} ; |
| | | } |
| | | } |
| | | } |
| | | if(!f.renameTo(new File(path + rtuAddr + ".log." + 1))){ |
| | | return new Object[]{null, 5} ; |
| | | } |
| | | //2024-10-11 上面rename了,应该不用delete了 |
| | | //if(!f.delete()){ |
| | | // return new Object[]{null, 6} ; |
| | | //} |
| | | |
| | | f = new File(path + rtuAddr + ".log"); |
| | | if(!f.exists()){ |
| | | if(f.createNewFile()){ |
| | | return new Object[]{f, 7} ; |
| | | }else{ |
| | | return new Object[]{null, 8} ; |
| | | } |
| | | } |
| | | }else{ |
| | | return new Object[]{f, 9} ; |
| | | } |
| | | }else{ |
| | | if(f.createNewFile()){ |
| | | return new Object[]{f, 10} ; |
| | | }else{ |
| | | return new Object[]{null, 11} ; |
| | | } |
| | | } |
| | | } 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 new Object[]{null, 12} ; |
| | | } |
| | | |
| | | /** |
| | | * 向文件中写入日志 |
| | | * @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) ; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |