Talk about puma's Parser

Keywords: Programming Java MySQL

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

doc

Posted by monkeypaw201 on Wed, 03 Jun 2020 07:39:03 -0700