
net.wicp.tams.commons.binlog.impl.BinglogReadByFile Maven / Gradle / Ivy
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