⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parsev3pmdatafile.java

📁 解析特定16进制文件
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/**
 * @(#)FileInfo.java	Nov 23, 2006 4:51:40 PM
 * 
 * COPYRIGHT DaTang Mobile Communications Equipment CO.,LTD
 */

package com.datangmobile.oss.omc.pc.v3file;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.datangmobile.oss.omc.common.exception.DatabaseException;
import com.datangmobile.oss.omc.common.nea.pm.pmdata.DefaultPmDataInput;
import com.datangmobile.oss.omc.common.nea.pm.pmdata.PmUtil;
import com.datangmobile.oss.omc.common.nea.pm.pmdata.TableConfig;
import com.datangmobile.oss.omc.common.server.pm.dto.GuideLineData;
import com.datangmobile.oss.omc.common.server.pm.dto.NameValue;
import com.datangmobile.oss.omc.common.server.pm.exception.FileParseException;
import com.datangmobile.oss.omc.pc.ConnectDB;
import com.datangmobile.oss.omc.pc.DeleteFileQueue;
import com.datangmobile.oss.omc.pc.IInsertDataIntoLatecyTable;
import com.datangmobile.oss.omc.pc.InsertDataIntoLatecyTable;
import com.datangmobile.oss.omc.pc.ParseFileExceptionQueue;
import com.datangmobile.oss.omc.pc.PmConst;
import com.datangmobile.oss.omc.pc.util.CounterGroupService;
import com.datangmobile.oss.omc.pc.util.DBConnectionException;
import com.datangmobile.oss.omc.pc.util.Database;
import com.datangmobile.oss.omc.pc.util.FileInfo;
import com.datangmobile.oss.omc.pc.util.IimUtil;
import com.datangmobile.oss.omc.pc.util.MsgInputStream;
import com.datangmobile.oss.omc.pc.util.NeMoi;
import com.datangmobile.oss.platform.util.ILogger;
import com.datangmobile.oss.platform.util.ModuleLogger;

/**
 * V3性能文件解析
 * 
 * 主要是解决GuideLineData入库时产生的"碎片记录". 所谓碎片记录是指本来一条数据库记录可以存储的数据,分成了多条记录.
 * 碎片记录会严重影响数据库的查询效率. 该类主要应用的技术如下 1)虚拟GuideLineData
 * 虚拟GuideLineData有多条相关的(在同一表且同一记录的)实际GuideLineData组成. 所以取10000为强制插入的经验值.
 * 如果该值,可能会导致内存溢出,太小则数据库会产生很多碎片记录. 2)对象池
 * 
 * 处于效率和空间平衡,不可能完全避免碎片记录
 * 
 * @author xingyong
 * @version 1.0
 * 
 */
public class ParseV3PMDataFile {

	/**
	 * 连接对象
	 */
	private Connection conn = null;

	private static final ILogger log = ModuleLogger.getPmLogger()
			.getOperLogger();

	// 因为conn会自动关闭,所以用保持数据库连接无效
	private static boolean useDBConnectonPool = false;

	// 由于不能保持数据库连接,用对象池几乎没有意义
	private static boolean useObjectPool = true;

	/**
	 * 用于缓存文件解析对象
	 */
	private static List<ParseV3PMDataFile> v3FileParserObjectPool = new ArrayList<ParseV3PMDataFile>();

	/**
	 * 用于缓存以数据库表记录为导向的GuideLine记录
	 */
	private Map<String, List<GuideLineData>> recordOrientedMap = new HashMap<String, List<GuideLineData>>();

	/**
	 * 用于缓存数据库连接的preparedstatement
	 */
	private Map<String, PreparedStatement> preparedStatementMap = new HashMap<String, PreparedStatement>();

	// 用于指示该实例是不是忙
	private boolean busy = true;

	// 用于标识如何批量处理的条数
	private int batchCounter = 0;

	/**
	 * 缺省的开始时间,因为同一个文件时间信息99.9%都是一样的,这样可以节省GuideLineData存储空间
	 */
	private Date defaultBeginTime;

	/**
	 * 缺省的开始时间,因为同一个文件时间信息99.9%都是一样的,这样可以节省GuideLineData存储空间
	 */
	private Date defaultEndTime;

	/**
	 * 用于记录同一dn的计数器是不是保存到同一的表,如果不一样那么表名计数器记录可以入库了
	 */
	private Map<String, String> tableAndDnMap = new HashMap<String, String>();

	/**
	 * 初始化插入计数器延迟表的类
	 */
	private IInsertDataIntoLatecyTable insertLatecyInfo = new InsertDataIntoLatecyTable();

	/**
	 * 该V2性能数据文件中V3计数器组的集合
	 */
	private Map<Integer, Set<Date>> v3CounterGroupMap = new HashMap<Integer, Set<Date>>();

	// private static Map<String,String> sqlMap =
	// Collections.synchronizedMap(new HashMap<String, String>());

	/**
	 * 查找一个空闲的文件解析实例. 返回实例前应该置busy为true
	 * 
	 * @param fileInfo
	 * @return 如果有异常则返回NULL
	 */
	public static synchronized ParseV3PMDataFile findIdleV3FileParser(
			FileInfo fileInfo) {

		if (v3FileParserObjectPool.size() > 16) {
			log.warn(ParseV3PMDataFile.class, "目前缓存V3性能文件解析实例数目过大,现在数目为:"
					+ v3FileParserObjectPool.size());
			log.warn(ParseV3PMDataFile.class, "清除解析实例");
			v3FileParserObjectPool.clear();
		}
		for (ParseV3PMDataFile fileParser : v3FileParserObjectPool) {
			if (fileParser.isBusy())
				continue;
			else {
				if (fileParser.init(fileInfo)) {
					fileParser.setBusy(true);
					log.debug(ParseV3PMDataFile.class, "复用以前的V3性能文件解析实例");
					return fileParser;
				} else
					return null;
			}
		}
		ParseV3PMDataFile fileParser = null;
		try {
			fileParser = new ParseV3PMDataFile(fileInfo);
			fileParser.setBusy(true);
		} catch (Exception e) {
			return null;
		}
		return fileParser;
	}

	/**
	 * 用于获取解析文件实例
	 * 
	 * @param fileInfo
	 * @return
	 */
	public static ParseV3PMDataFile getV3FileParser(FileInfo fileInfo) {
		ParseV3PMDataFile fileParser = null;
		try {
			fileParser = new ParseV3PMDataFile(fileInfo);
			// fileParser.setBusy(true);
		} catch (Exception e) {
			return null;
		}
		return fileParser;
	}

	/**
	 * 构造器
	 */
	private ParseV3PMDataFile(FileInfo fileInfo) throws Exception {
		// 初始化
		if (!init(fileInfo)) {
			throw new Exception("初始化V3性能文件解析错误");
		}
		if (useObjectPool)
			v3FileParserObjectPool.add(this);
	}

	/**
	 * 初始化
	 * 
	 * @throws SQLException
	 * @throws IOException
	 * @throws DBConnectionException
	 */
	private boolean init(FileInfo fileInfo) {
		try {
			/**
			 * 加入连接数据库的部分 设置提交模式为不是自动提交模式
			 */
			if (conn == null || conn.isClosed()) {
				conn = Database.connect();
				conn.setAutoCommit(false);
				preparedStatementMap.clear();
				// log.debug(this.getClass(), "为V3性能文件解析创建数据库连接");
			} else {
				// 复用以前的连接
				log.debug(this.getClass(), "复用以前的数据库连接及相关PreparedStatement");
			}
			return true;
		} catch (Exception ex) {
			log.error("数据库不能连接", ex);
			// 重新将文件放入队列中,等待解析
			reputParseQueue(fileInfo, FileInfo.DB_EXCEPTION);
			// 将数据库的状态置为不可用
			ConnectDB.getInstance().setConnectSuccess(false);
			return false;
		}

	}

	/**
	 * 用于统一处理时间信息的保存,如果和缺省的时间不一样,就设置到GuideLineData实例里,如果一样就免了
	 * 
	 * @param data
	 * @param endTimeSetInV3Group
	 */
	private void readTimeInfo(MsgInputStream msgInStream,
			GuideLineData guideLineData, Set<Date> endTimeSetInV3Group) {

		/*
		 * 开始时间 modify by liuyuan 2007-4-9 根据o接口读取的为UINT32 用java中的long型保存
		 * BUGCN00015626
		 * 
		 * modify by liuyuan 2008-6-11 CNBUG00019010 OMC负责把秒数归0
		 */
		Date beginTime = PmUtil.getWholeDate(new Date(
				msgInStream.readUInt() * 1000), Calendar.SECOND);

		/*
		 * 结束时间 modify by liuyuan 2007-4-9 根据o接口读取的为UINT32 用java中的long型保存
		 * BUGCN00015626
		 */
		Date endTime = PmUtil.getWholeDate(new Date(
				msgInStream.readUInt() * 1000), Calendar.SECOND);

		if (defaultBeginTime == null) {
			defaultBeginTime = beginTime;
		}
		if (defaultEndTime == null) {
			defaultEndTime = endTime;
		}

		if (!beginTime.equals(defaultBeginTime))
			guideLineData.setBegin(beginTime);
		if (!endTime.equals(defaultEndTime))
			guideLineData.setEnd(endTime);

		endTimeSetInV3Group.add(endTime);
	}

	/**
	 * 解析文件
	 * 
	 * @param file
	 *            文件
	 * @param type
	 *            上传文件的网元类型
	 * @throws FileNotFoundException
	 * @throws IOException
	 * @throws SQLException
	 * @throws InterruptedException
	 * @throws SQLException
	 * @throws IOException
	 */
	public void parseFileAndInsertDB(FileInfo fileinfo) {
		long beginTestTime = System.currentTimeMillis();

		busy = true;
		int error = 32;
		// 对整个解析过程都需要捕捉异常
		FileInputStream filein = null;
		DataInputStream datain = null;

		File file = fileinfo.getFile();
		String type = fileinfo.getNeType();

		String fileName = file.getName();
		String[] splitNames = fileName.split("_");

		// 从文件名中获取rnc的ID号
		int rncId = 0;
		try {
			// 名字形如:pm_rnc_0010_20080819_0400.dat(4.00.00)
			// rncId = Integer.valueOf(splitNames[2], 16);
			// 名字形如:pm1218990600_rnc_0012.dat(3.40.300)
			String rncSt = splitNames[2].replace('.', '_');
			rncId = Integer.valueOf(rncSt.split("_")[0], 16);
		} catch (Exception ex) {
			log.error("文件名不合规范,不能取到RNC的ID号。fileName: " + file.getName(), ex);
			File f = new File(PmConst.PM_DIR + File.separator + file.getName()
					+ ".bad");
			boolean save = file.renameTo(f);
			if (save) {
				log.error(ParseV3PMDataFile.class, "保存文件为 " + f.getName()
						+ " 成功");
			} else {
				log.error(ParseV3PMDataFile.class, "保存文件为 " + f.getName()
						+ " 失败");
			}
			return;
		}

		/*
		 * 记录每个记录的字节个数 用来判断是否已经到了一条记录的结束
		 */
		int count = 0;
		int dataCount = 0;
		int insertCount = 0;

		try {

			filein = new FileInputStream(file);
			datain = new DataInputStream(filein);

			log.info(ParseV3PMDataFile.class, "Ready to parse file:"
					+ file.getAbsoluteFile() + " File type:" + type + " rncId:"
					+ rncId);
			// long begin = System.currentTimeMillis();
			/* 跳过头部 */
			datain.skipBytes(32);
			// count = count + 32;
			while (datain.available() > 0) {

				// 本条记录的字节个数
				int lRecordLen = datain.readInt();
				// count = count + 4;
				byte[] body = new byte[lRecordLen];

				// log.debug(ParseV3DataFile.class, " read byte[] use time begin
				// " +
				// System.currentTimeMillis());
				datain.read(body);
				// log.debug(ParseV3DataFile.class, " read byte[] use time end "
				// +
				// System.currentTimeMillis());

				MsgInputStream msgInStream = new MsgInputStream(body);

				msgInStream.skipBytes(14);
				count = count + 14;

				// 计数器组ID
				int groupId = msgInStream.readShort();
				count = count + 2;

				ArrayList<String> names = null;
				try {
					names = CounterGroupService.getInstance().getCounterNames(
							groupId);
				} catch (Exception e) {
					log

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -