package org.infosec.ismp.situation.manager;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.infosec.ismp.situation.calculate.substep.AttackReckon;
import org.infosec.ismp.situation.calculate.substep.IllicitConnectReckom;
import org.infosec.ismp.situation.calculate.substep.VirusReckon;
import org.infosec.ismp.situation.dao.RecordIndexDao;
import org.infosec.ismp.situation.model.Event;
import org.infosec.ismp.situation.util.ConstantSource;
/**
* 此线程用来调度先入先出队列。
* 将收到的报文分组后重新放入一个新的先入先出队列。
* @author cc
* 2010-10-11 16:48:11
*/
public class SituationProcess extends Thread {
private int columnNum = 0;///将事件按照分析时间分组后,用columnNum来统计一组内事件的数量。
private Timestamp time;///开始分组时间
private Timestamp lastTime;///上次list的最后一组时间
private int index = 1;
private long analyseTime = ConstantSource.ANALYSETIME;///数据分析时间间隔
private static boolean flag = true;///标志位
/**
* 记录指针Dao
*/
private RecordIndexDao recordIndexDao;
public void setRecordIndexDao(RecordIndexDao recordIndexDao) {
this.recordIndexDao = recordIndexDao;
}
/**
* 注入病毒计数计算器
*/
private VirusReckon virusReckon;
public void setVirusReckon(VirusReckon virusReckon) {
this.virusReckon = virusReckon;
}
/**
* 注放非法连接计数计算器
*/
private IllicitConnectReckom illicitConnectReckom;
public void setIllicitConnectReckom(
IllicitConnectReckom illicitConnectReckom) {
this.illicitConnectReckom = illicitConnectReckom;
}
/**
* 攻击计数计算器
*/
private AttackReckon attackReckon;
public void setAttackReckon(AttackReckon attackReckon) {
this.attackReckon = attackReckon;
}
private SituationSaveToDB situationSaveToDB;
public void setSituationSaveToDB(SituationSaveToDB situationSaveToDB) {
this.situationSaveToDB = situationSaveToDB;
}
///先入先出队列(线程安全):这个队列用来存分组前收集到的事件。
private BlockingQueue<Event> queueEvent;
private ArrayList<Event> listEvent = new ArrayList<Event>();///解析数据报中的事件数据,存放到listEvent(有序)。
private long startTime;
private long endTime;
private int eventId = 0;
private int recordId;
protected final Log log = LogFactory.getLog(getClass());
public void setQueueEvent(BlockingQueue<Event> queueEvent) {
this.queueEvent = queueEvent;
}
public void init() {
// Timestamp time2 = null;
// List<RecordIndex> recordIndexs = recordIndexDao.getAll();///获取读取位置表类集合(集合中只有最后一条读取位置)
// Timestamp time1 = eventDao.getEventsStartTime();///取得最早的事件发生时间
// if (recordIndexs != null && recordIndexs.size() > 0) {
// RecordIndex recordIndex = recordIndexs.get(0);///取得最后的一条读取位置记录
// recordId = recordIndex.getId();
// eventId = recordIndex.getColumnNumber();///取得表读取位置,赋值给eventId
// time2 = recordIndex.getTime();///取得表读取位置表类的时间
// if (recordId>0) {
// situationSaveToDB.setRecordId(recordId);
// }
// } else {
// eventId = 0;///如果读取位置表集合中没有数据,则eventId为0
// }
//
// ///将最早的事件发生时间 和 最后一条表读取位置表的时间比较后,最晚的那个赋值给time
// if (time1 != null || time2 != null) {
// if (time1 != null && time2 != null) {
// if (time1.getTime() > time2.getTime()) {
// time = time1;
// } else {
// time = time2;
// }
// } else if (time1 != null && time2 == null) {
// time = time1;
// }else if (time1==null && time2 !=null) {
// time = new Timestamp(System.currentTimeMillis());
// }
// } else {
// ///如果两个时间都为null,则选取当前时间。
// time = new Timestamp(System.currentTimeMillis());
// }
}
@Override
public void run() {
try {
Event firstEvent = queueEvent.take();///取出队列中的第一个事件
time = firstEvent.getTime();///第一个事件的时间。
listEvent.add(firstEvent);
Timer timer = new Timer();///计时器
timer.schedule(new TimerTask() {
public void run() {
flag = !flag;///延迟一分钟之后每隔一分钟改变一次
System.out.println("此时标志位为 :" + flag );
}
}, 1000*20, 1000*20);///30秒之后改变:下次改变是10分钟,为了测试,以后用常量来代替
while(true){
if(flag){
// System.out.println("消费一个事件");
///tack()是线程安全的。获取并移除此队列的头部,在元素变得可用之前一直等待
Event _event = queueEvent.take();///取出队列中的一个事件
// long startRange = time.getTime();
// long endRange = time.getTime() + 60000;
// listEvent = getListEventByTime(startRange,endRange);
listEvent.add(_event);
} else if(null != listEvent && listEvent.size() > 0) {
// time = listEvent.get(0).getTime();
if(null == lastTime){
// time = listEvent.get(0).getTime();
time = new Timestamp(listEvent.get(0).getTime().getTime()-1000);///这批事件的起始时间。
}else if(lastTime.getTime() <= listEvent.get(0).getTime().getTime()){
time = lastTime ;
}else {
time = new Timestamp(listEvent.get(0).getTime().getTime()-1000);///这批事件的起始时间。
}
// endTime = time.getTime()-1000;///这批事件的起始时间。
endTime = time.getTime();///这批事件的起始时间。
for (int i = 0; i < listEvent.size(); i++) {
Event event = listEvent.get(i);///依次取出某个事件。
startTime = event.getTime().getTime();///这个事件的发生时间。
if ((startTime - endTime) <= analyseTime) {///小于等于分析时间,则说明分到当前组。
// time = event.getTime();///cc:将这个事件的发生时间赋值给time?
columnNum++;///分组内 事件数量计数器。
int type = event.getType();///判断这个事件的类型。根据事件类型选择对应的计算器。
switch (type) {
case 1:
attackReckon.analyzeEvent(event);///分析事件:将攻击事件的优先级和IP放入hashmap里。
break;
case 2:
virusReckon.analyzeEvent(event);///分析事件:将病毒事件的优先级和IP放入hashmap里。
break;
case 3:
illicitConnectReckom.analyzeEvent(event);///分析事件:将非法连接事件的优先级和IP放入hashmap里。
break;
}
} else {///大于分析时间,则说明这个事件已经不属于当前分组,一轮分组结束。
attackReckon.reckonExponential(time, index);///计算攻击指数
virusReckon.reckonExponential(time, index);///计算病毒指数
illicitConnectReckom.reckonExponential(time, index);///计算非法连接指数
long t1 = startTime - endTime;///当前事件与这批事件起始时间的相差毫秒数。(这里的相差毫秒数肯定大于一个分析时间)
t1 = t1 % analyseTime;///超出单位分析时间的部分。
endTime = startTime - t1;///分组中最后一个事件的发生时间-这个事件超出单位分析时间的部分=分组的截止时间。
time = new Timestamp(endTime);///将这个分组的截止时间(倍数)赋值给time,作为下个分组的起始时间。
i--;///如果不i--,每次分组计算一次态势则会错过一个事件。因为此时当前的事件已经是下个分组的第一个事件了。
log.info("生成第" + index + "次运算!!!");
index++;///每计算一次,index加1
columnNum = 0;///分组内事件计数器清零。下个分组开始
}
if(i == (listEvent.size()-1)){
lastTime = time;///保存最后一次分组的最后时间
listEvent.clear();
}
}
}
// if(listEvent.size() >= ConstantSource.LISTSIZE){
////
//
// }
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}