1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
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 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) ;
                }
            }
        }
    }
    
}