All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.wicp.tams.commons.binlog.impl.BinglogReadByFile Maven / Gradle / Ivy

There is a newer version: 2.3.4
Show newest version
package net.wicp.tams.commons.binlog.impl;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.commons.Result;
import net.wicp.tams.commons.apiext.ByteUtil;
import net.wicp.tams.commons.beans.Host;
import net.wicp.tams.commons.binlog.IBinlogRead;
import net.wicp.tams.commons.binlog.IEventRead;
import net.wicp.tams.commons.binlog.bean.CountNum;
import net.wicp.tams.commons.binlog.bean.EventBean;
import net.wicp.tams.commons.binlog.bean.EventHeader;
import net.wicp.tams.commons.binlog.bean.Pos;
import net.wicp.tams.commons.binlog.bean.TableMapBean;
import net.wicp.tams.commons.binlog.constant.BinLogVersion;
import net.wicp.tams.commons.binlog.constant.EventFlag;
import net.wicp.tams.commons.binlog.constant.EventType;
import net.wicp.tams.commons.binlog.event.AbsEvent;
import net.wicp.tams.commons.binlog.event.FormatDescription;
import net.wicp.tams.commons.binlog.event.rows.RowsEvent;
import net.wicp.tams.commons.binlog.sender.ISender;
import net.wicp.tams.commons.io.InputStreamRamdomRead;

/***
 * 读日志通过文件
 * 
 * @author zhoujunhui
 *
 */
@Slf4j
public class BinglogReadByFile extends InputStreamRamdomRead implements IBinlogRead {
	private EventBean firstEvent;
	private final String fileName;
	private final ISender[] senders;
	private long curTime = 0;
	private long insertNum = 0;
	private long updateNum = 0;
	private long deleteNum = 0;

	public BinglogReadByFile(File file, ISender... senders) throws IOException {
		super(file);
		this.fileName = file.getName();
		if (senders != null && senders.length > 0) {// senders.length > 0不能
			this.senders = senders;
		} else {
			this.senders = null;
		}
		Host host = AbsEvent.hosts.get();
		if (host == null) {
			host = Host.builder().hostIp("127.0.0.1").port(3306).defaultDb("mysql").user("root").pwd("111111").build();// 模拟一个host
			// fileName.hashCode()
			AbsEvent.hosts.set(host);
		}
	}

	public BinglogReadByFile(File file, String dbPattern, String tbPattern, ISender... senders) throws IOException {
		this(file, senders);
		TableMapBean.dbPattern = dbPattern;
		TableMapBean.tbPattern = tbPattern;
	}

	@Override
	public Result checkHead() {
		try {
			final byte[] magic = this.readBytes(BINLOG_MAGIC.length);
			if (!Arrays.equals(magic, BINLOG_MAGIC)) {
				return Result.getError(String.format("不合法的binlog文件:[%s]", fileName));
			} else {
				firstEvent = readEvent();
				BinLogVersion binLogVersion = getVersion(firstEvent.getHead());
				if (binLogVersion == null || binLogVersion != BinLogVersion.v4) {
					return Result.getError(String.format("只支持v4的binlog,不支持的binlog版本:[%s]",
							binLogVersion == null ? "" : binLogVersion.name()));
				}
				return Result.getSuc();
			}
		} catch (Exception e) {
			return Result.getError(String.format("读binlog文件:[%s]错误", fileName));
		}
	}

	// 需要在第9个位开始读,读13位
	public BinLogVersion getVersion(EventHeader firstHead) {
		if (firstHead == null) {
			return null;
		}
		BinLogVersion retobj = null;
		switch (firstHead.getEventType()) {
		case FORMAT_DESCRIPTION_EVENT:
			retobj = BinLogVersion.v4;
			break;
		case START_EVENT_V3:
			long eventSize = firstHead.getEventSize();
			if (eventSize == (13 + 56)) {
				return BinLogVersion.v1;
			} else if (eventSize == (19 + 56)) {
				return BinLogVersion.v3;
			}
			break;
		default:
			break;
		}
		return retobj;
	}

	@Override
	public void read(long pos) throws IOException {
		Result checkRet = checkHead();
		if (!checkRet.isSuc()) {
			throw new RuntimeException(checkRet.getMessage());
		}
		// 初始化FormatDescription信息 firstEventHeader
		IEventRead reader = new FormatDescription(firstEvent);
		reader.parseBody(senders);
		if (pos > firstEvent.getHead().getNextEventPos()) {
			this.seek(pos);
		}
		while (true) {
			EventBean curEvent = readEvent();
			curTime = curEvent.getHead().getTimestamp();
			reader = curEvent.getEventRead();
			Result ret = null;
			if (reader instanceof RowsEvent) {
				ret = reader.parseBody(senders);
			} else {
				ret = reader.parseBody();
			}
			if (ret != null) {
				log.info(ret.getMessage());
			}
			// 统计增、删、改
			if (curEvent.getEventRead() instanceof RowsEvent) {
				RowsEvent rd = (RowsEvent) curEvent.getEventRead();
				switch (rd.getOptType()) {
				case insert:
					insertNum++;
					break;
				case update:
					updateNum++;
					break;
				case delete:
					deleteNum++;
					break;
				default:
					break;
				}
			}
		}

	}

	private EventBean readEvent() throws IOException {
		if (this.available() <= 0) {
			return null;
		}
		long timestamp = ByteUtil.readLongL(readBytes(4));
		EventType eventType = EventType.get(readByte());
		long serverId = ByteUtil.readLongL(readBytes(4));
		long eventSize = ByteUtil.readLongL(readBytes(4));
		long nextEventPos = ByteUtil.readLongL(readBytes(4));
		EventFlag eventFlag = EventFlag.get(ByteUtil.readIntL(readBytes(2)));
		byte[] body = readBytes((int) eventSize - 19);
		EventHeader head = EventHeader.builder().timestamp(timestamp).eventType(eventType).serverId(serverId)
				.eventSize(eventSize).nextEventPos(nextEventPos).eventFlag(eventFlag).build();
		EventBean retobj = new EventBean(head, body);

		log.info(
				"---------------------------事件[{}]开始位置:{},数据开始位置{}----------------------------------------------------",
				eventType == null ? "" : eventType.name(), AbsEvent.row(retobj.getBeginHead()),
				AbsEvent.row(retobj.getBeginBody()));
		return retobj;
	}

	@Override
	public Pos curPos() {
		Pos ret = new Pos();
		ret.setFileName(fileName);
		ret.setPos(getCurPos());
		ret.setTime(curTime);
		return ret;
	}

	@Override
	public void resetNum() {
		insertNum = 0;
		updateNum = 0;
		deleteNum = 0;
	}

	@Override
	public CountNum getCountNum() {
		CountNum countNum = CountNum.builder().insertNum(insertNum).updateNum(updateNum).deleteNum(deleteNum).build();
		return countNum;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy