package com.nms.server.thread.errorinfo;

import java.util.Calendar;
import java.util.LinkedList;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

import com.nms.server.bean.NmsErrorInfo;
import com.nms.server.common.Common;
import com.nms.server.common.Constants;
import com.nms.server.dao.CommonDao;
import com.nms.server.util.ExceptionPrintUtils;
import com.nms.server.util.FileUtils;

public class ErrorInfoResoveManagerThread implements Runnable{
	private Logger logger = Logger.getLogger(ErrorInfoResoveManagerThread.class);
	private int testNum = 0;//尝试运行线程Constants.DETEC_DATA_RESOVE的次数

	public void run() {
		//将线程运行程序，尽可能的catch捕获异常
//		Thread.currentThread().setName("DC错误信息解析管理线程");
		Thread.currentThread().setName("DC Error Message Parsing Management Threads");
		try {
		boolean runFlag = Common.isDbConnected();//测试数据库连接
		
		//- 检查线程运行状态  运行中无操作
		Future<?> future = Common.getFutureMap().get(Constants.ERROR_INFO_RESOVE);
		if(future != null && !future.isCancelled() && !future.isDone() && runFlag){	//运行中
			runFlag = false;
			logger.info("DC错误信息解析执行线程 运行中 不再启动新解析线程");
		}
			
		/*
		 * 连续超过Constants.CHECK_WARNING_DATA_OVERRUN次数时，将数据存入硬盘中
		 * 否则 正常执行数据解析线程
		 * */
		if(!runFlag){	//判断并结束线程
			testNum = (testNum%Constants.CHECK_WARNING_DATA_OVERRUN);
			testNum++;
			if(testNum==Constants.CHECK_WARNING_DATA_OVERRUN) {
				if(Constants.FLAG_ERROR_DATA_SAVE_DISK_RESOVE==1) {		
					/*
					 * 连续多个周期仍未解析完成
					 * 说明list里存有大量的数据，则先将当前未解析的数据列表存入硬盘，
					 * 然后停掉解析线程，将正在解析的数据列表中的剩余数据存入硬盘
					 * */
					logger.warn("Create a database connection failure and data stored to the hard disk");
					saveErrorDataToDisk();
				}
			}
			return;
		}else{		//重置计数器 程序继续执行
			testNum = 1;
			
		}
			
		//- 非升级操作判断
		if(Common.SERVER_UN_UPGRADE_FLAG){
			
			//- 为空或空闲中 变更存储区 启动新解析线程
			Common.changeErrorInfoFlag();	//变更数据存放集合
			
			LinkedList<NmsErrorInfo> dsbList =  Common.getErrorInfoList();	// 获取非存放状态的数据集合
			if(dsbList != null && dsbList.size()>0){
				logger.info("DC错误信息解析执行线程  空闲中 启动新解析线程");
				//-- 获取线程执行 需进行主动告警和邮件通知等相关操作，待考虑
				future = Common.service.submit(new ErrorInfoResoveThread("DC错误信息解析执行线程",dsbList));
				//注册
				Common.getFutureMap().put(Constants.ERROR_INFO_RESOVE, future);
			}else{
				logger.info("获取到的集合中数据数量为0，无需启动解析线程");
			}
		}

		} catch (Exception e) {
			logger.error(ExceptionPrintUtils.printExceptionStack(e));
		}finally{ 
		logger.debug("执行结束");
		}
	}
	
	/**
	 * 数据库是否可连接判断
	 * @time Mar 7, 2013-2:22:42 PM
	 * @return
	 */
	public boolean dbTest() {
		CommonDao dao = null;
		try {
//			if(!false)throw new Exception("强制异常");
			dao = new CommonDao();
			logger.debug("尝试获取数据库连接成功");
			return true;
		} catch (Exception e) {
			logger.error("Try to get a database connection failure", e);
			/* 告警 */
			return false;
		}finally{
			if(dao!=null){
				dao.close();
				dao=null;
			}
		}
	}
	
	////2013-2-19 hyx ：当监测数据量过大时，将数据先存放到硬盘，再定时入库（由单独的定时线程实现）
	public void saveErrorDataToDisk() {
		LinkedList<NmsErrorInfo> notResolvingErrorInfoList =  Common.getNotResovlingErrorInfoList();	// 获取未在解析的监测数据集合
		try {
			
			//终止正在解析监测数据的线程，并将正在解析的list里未解析的数据存入硬盘
			Future<?> future = Common.getFutureMap().get(Constants.DETEC_DATA_RESOVE);
			if(future != null && !future.isCancelled() && !future.isDone()){	//运行中
				future.cancel(true);
			}
			LinkedList<NmsErrorInfo> detectDataList = Common.getErrorInfoList();	// 获取非存放状态的数据集合(正在解析的list)
			saveByteToFile(detectDataList);
			
			//将未在解析的list存放到硬盘上
			saveByteToFile(notResolvingErrorInfoList);			
			
		}catch(IndexOutOfBoundsException e) {
			logger.error("When monitoring data is too much, the data is stored in the hard disk exception",e);
		}catch (Exception e) {
			logger.error(ExceptionPrintUtils.printExceptionStack(e));
		}
			
	}
	
	private void saveByteToFile(LinkedList<NmsErrorInfo> dataList) {
		String filePath = "";
		int dataSize = dataList.size();//如果不按此时的size来操作，则list里的数据可能会一直在增加，就会一直循环下去？
		logger.info("错误数据过多，共"+dataSize+"条错误数据，等待存入硬盘");
		try {
			for(int j=0;j<dataSize;j++) {
				if(dataList.size()>0) {
					NmsErrorInfo data= dataList.get(0);//因为每次循环都会dataList.remove(0);所以每次操作的都是第0条记录
					filePath = Constants.OVERRUN_DETEC_FILE_DIR+"/"+Common.getDateDirName()+"/"+Calendar.getInstance().getTimeInMillis()+"_"+j+".csv";
//					FileUtils.wirteBytesToFile(data, filePath);//此处暂时将错误信息抛弃
					logger.info("被抛弃的DC ErrorInfo:"+data.getErrorCode()+"-"+data.getErrortDesc()+"="+data.getErrortGetip()+"="+data.getErrortIp()+"="+data.getErrorTime());
					dataList.remove(0);
					logger.info("监测数据过多，已保存至"+filePath);
				}
			}
			
		}catch(Exception e) {
			logger.error("When monitoring data is too much, the data is stored in the hard disk exception",e);
		}
	}

	public static void main(String [] args) {
		Common.scheduled.scheduleAtFixedRate(new ErrorInfoResoveManagerThread(),0,50,TimeUnit.SECONDS);
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.exit(0);
	}
}
