order
This paper mainly studies the Parser of puma
Parser
puma/puma/src/main/java/com/dianping/puma/parser/Parser.java
public interface Parser extends LifeCycle { BinlogEvent parse(ByteBuffer buf, PumaContext context) throws IOException; }
- The Parser inherits the life cycle interface, which defines the parse method and resolves ByteBuffer to BinlogEvent
DefaultBinlogParser
puma/puma/src/main/java/com/dianping/puma/parser/DefaultBinlogParser.java
@ThreadSafe public class DefaultBinlogParser implements Parser { private final Logger logger = LoggerFactory.getLogger(DefaultBinlogParser.class); private static Map<Byte, Class<? extends BinlogEvent>> eventMaps = new ConcurrentHashMap<Byte, Class<? extends BinlogEvent>>(); @Override public BinlogEvent parse(ByteBuffer buf, PumaContext context) throws IOException { logger.debug("\n\n\n"); logger.debug("****************************** binlog parse begin ******************************"); BinlogHeader header = new BinlogHeader(); header.parse(buf, context); logger.debug("binlog event header:\n"); logger.debug("{}", header); BinlogEvent event = null; Class<? extends BinlogEvent> eventClass = eventMaps.get(header.getEventType()); if (eventClass != null) { try { event = eventClass.newInstance(); } catch (Exception e) { logger.error("Init event class failed. eventType: " + header.getEventType(), e); event = null; } } if (event == null) { event = new PumaIgnoreEvent(); } logger.debug("binlog event type:\n"); logger.debug("{}", event.getClass()); event.parse(buf, context, header); logger.debug("binlog event:\n"); logger.debug("{}", event); logger.debug("****************************** binlog parse end ******************************"); logger.debug("\n\n\n"); return event; } /* * (non-Javadoc) * * @see com.dianping.puma.common.LifeCycle#start() */ @Override public void start() { eventMaps.put(BinlogConstants.UNKNOWN_EVENT, UnknownEvent.class); eventMaps.put(BinlogConstants.QUERY_EVENT, QueryEvent.class); eventMaps.put(BinlogConstants.STOP_EVENT, StopEvent.class); eventMaps.put(BinlogConstants.ROTATE_EVENT, RotateEvent.class); eventMaps.put(BinlogConstants.INTVAR_EVENT, IntVarEvent.class); eventMaps.put(BinlogConstants.RAND_EVENT, RandEvent.class); eventMaps.put(BinlogConstants.USER_VAR_EVENT, UserVarEvent.class); eventMaps.put(BinlogConstants.FORMAT_DESCRIPTION_EVENT, FormatDescriptionEvent.class); eventMaps.put(BinlogConstants.XID_EVENT, XIDEvent.class); eventMaps.put(BinlogConstants.TABLE_MAP_EVENT, TableMapEvent.class); eventMaps.put(BinlogConstants.WRITE_ROWS_EVENT_V1, WriteRowsEvent.class); eventMaps.put(BinlogConstants.UPDATE_ROWS_EVENT_V1, UpdateRowsEvent.class); eventMaps.put(BinlogConstants.DELETE_ROWS_EVENT_V1, DeleteRowsEvent.class); eventMaps.put(BinlogConstants.INCIDENT_EVENT, IncidentEvent.class); //mysql --5.6 eventMaps.put(BinlogConstants.WRITE_ROWS_EVENT, WriteRowsEvent.class); eventMaps.put(BinlogConstants.UPDATE_ROWS_EVENT, UpdateRowsEvent.class); eventMaps.put(BinlogConstants.DELETE_ROWS_EVENT, DeleteRowsEvent.class); eventMaps.put(BinlogConstants.HEARTBEAT_LOG_EVENT, HeartbeatEvent.class); eventMaps.put(BinlogConstants.IGNORABLE_LOG_EVENT, IgnorableEvent.class); eventMaps.put(BinlogConstants.ROWS_QUERY_LOG_EVENT, RowsQueryEvent.class); eventMaps.put(BinlogConstants.GTID_LOG_EVENT, GtidEvent.class); eventMaps.put(BinlogConstants.ANONYMOUS_GTID_LOG_EVENT, AnonymousGtidEvent.class); eventMaps.put(BinlogConstants.PREVIOUS_GTIDS_LOG_EVENT, PreviousGtidsEvent.class); } @Override public void stop() { } }
- DefaultBinlogParser implements the Parser interface, and its parse method adopts the header.getEventType() instantiate the corresponding BinlogEvent first, and then pass the event.parse(buf, context, header) for parsing
BinlogEvent
puma/puma/src/main/java/com/dianping/puma/parser/mysql/event/BinlogEvent.java
public interface BinlogEvent extends Serializable { BinlogHeader getHeader(); void setHeader(BinlogHeader header); void parse(ByteBuffer buf, PumaContext context, BinlogHeader header) throws IOException; }
- BinlogEvent interface defines getHeader, setHeader and parse methods
AbstractBinlogEvent
puma/puma/src/main/java/com/dianping/puma/parser/mysql/event/AbstractBinlogEvent.java
public abstract class AbstractBinlogEvent implements BinlogEvent { private static final long serialVersionUID = -8136236885229956889L; private BinlogHeader header; private int checksumAlg = BinlogConstants.CHECKSUM_ALG_OFF; private long crc; @Override public void parse(ByteBuffer buf, PumaContext context, BinlogHeader header) throws IOException { this.header = header; doParse(buf, context); if (!(this.header.getEventType() == BinlogConstants.ROTATE_EVENT)) { checksumAlg = context.getChecksumAlg(); // fetch checksum alg parseCheckSum(buf); } } @Override public BinlogHeader getHeader() { return header; } @Override public void setHeader(BinlogHeader header) { this.header = header; } public abstract void doParse(ByteBuffer buf, PumaContext context) throws IOException; private void parseCheckSum(ByteBuffer buf) { if (checksumAlg != BinlogConstants.CHECKSUM_ALG_OFF && checksumAlg != BinlogConstants.CHECKSUM_ALG_UNDEF) { buf.position((int) (this.header.getEventLength() - 4)); setCrc(PacketUtils.readLong(buf, 4)); } } @Override public String toString() { return new ToStringBuilder(this) .append("header", header) .append("checksumAlg", checksumAlg) .append("crc", crc) .toString(); } public void setChecksumAlg(int checksumAlg) { this.checksumAlg = checksumAlg; } public int getChecksumAlg() { return checksumAlg; } public long getCrc() { return crc; } public void setCrc(long crc) { this.crc = crc; } public boolean isRemaining(ByteBuffer buf, PumaContext context) { return context.isCheckSum() ? buf.remaining() - 4 > 0 : buf.hasRemaining(); } public int lenRemaining(ByteBuffer buf, PumaContext context) { return context.isCheckSum() ? buf.remaining() - 4 : buf.remaining(); } }
- AbstractBinlogEvent declaration implements BinlogEvent interface. Its parse method will call doParse method, and then for non ROTATE_EVENT will execute parseCheckSum
Summary
The Parser inherits the life cycle interface, which defines the parse method and resolves ByteBuffer to BinlogEvent; the DefaultBinlogParser implements the Parser interface through header.getEventType() instantiate the corresponding BinlogEvent first, and then pass the event.parse(buf, context, header) for parsing