content: package com.taobao.tddl.dbsync.binlog;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import com.taobao.tddl.dbsync.binlog.event.LogHeader;
  
  /**
   * Binary log event definitions. This includes generic code common to all types
   * of log events, as well as specific code for each type of log event. - All
   * numbers, whether they are 16-, 24-, 32-, or 64-bit numbers, are stored in
   * little endian, i.e., the least significant byte first, unless otherwise
   * specified. representation of unsigned integers, called Packed Integer. A
   * Packed Integer has the capacity of storing up to 8-byte integers, while small
   * integers still can use 1, 3, or 4 bytes. The value of the first byte
   * determines how to read the number, according to the following table:
   * <table>
   * <caption>Format of Packed Integer</caption>
   * <tr>
   * <th>First byte</th>
   * <th>Format</th>
   * </tr>
   * <tr>
   * <td>0-250</td>
   * <td>The first byte is the number (in the range 0-250), and no more bytes are
   * used.</td>
   * </tr>
   * <tr>
   * <td>252</td>
   * <td>Two more bytes are used. The number is in the range 251-0xffff.</td>
   * </tr>
   * <tr>
   * <td>253</td>
   * <td>Three more bytes are used. The number is in the range 0xffff-0xffffff.</td>
   * </tr>
   * <tr>
   * <td>254</td>
   * <td>Eight more bytes are used. The number is in the range
   * 0xffffff-0xffffffffffffffff.</td>
   * </tr>
   * </table>
   * - Strings are stored in various formats. The format of each string is
   * documented separately.
   * 
   * @see mysql-5.1.60/sql/log_event.h
   * @author <a href="mailto:changyuan.lh@taobao.com">Changyuan.lh</a>
   * @version 1.0
   */
  public abstract class LogEvent {
  
      /*
       * 3 is MySQL 4.x; 4 is MySQL 5.0.0. Compared to version 3, version 4 has: -
       * a different Start_log_event, which includes info about the binary log
       * (sizes of headers); this info is included for better compatibility if the
       * master's MySQL version is different from the slave's. - all events have a
       * unique ID (the triplet (server_id, timestamp at server start, other) to
       * be sure an event is not executed more than once in a multimaster setup,
       * example: M1 / \ v v M2 M3 \ / v v S if a query is run on M1, it will
       * arrive twice on S, so we need that S remembers the last unique ID it has
       * processed, to compare and know if the event should be skipped or not.
       * Example of ID: we already have the server id (4 bytes), plus:
       * timestamp_when_the_master_started (4 bytes), a counter (a sequence number
       * which increments every time we write an event to the binlog) (3 bytes).
       * Q: how do we handle when the counter is overflowed and restarts from 0 ?
       * - Query and Load (Create or Execute) events may have a more precise
       * timestamp (with microseconds), number of matched/affected/warnings rows
       * and fields of session variables: SQL_MODE, FOREIGN_KEY_CHECKS,
       * UNIQUE_CHECKS, SQL_AUTO_IS_NULL, the collations and charsets, the
       * PASSWORD() version (old/new/...).
       */
      public static final int    BINLOG_VERSION                           = 4;
  
      /* Default 5.0 server version */
      public static final String SERVER_VERSION                           = "5.0";
  
      /**
       * Event header offsets; these point to places inside the fixed header.
       */
      public static final int    EVENT_TYPE_OFFSET                        = 4;
      public static final int    SERVER_ID_OFFSET                         = 5;
      public static final int    EVENT_LEN_OFFSET                         = 9;
      public static final int    LOG_POS_OFFSET                           = 13;
      public static final int    FLAGS_OFFSET                             = 17;
  
      /* event-specific post-header sizes */
      // where 3.23, 4.x and 5.0 agree
      public static final int    QUERY_HEADER_MINIMAL_LEN                 = (4 + 4 + 1 + 2);
      // where 5.0 differs: 2 for len of N-bytes vars.
      public static final int    QUERY_HEADER_LEN                         = (QUERY_HEADER_MINIMAL_LEN + 2);
  
      /* Enumeration type for the different types of log events. */
      public static final int    UNKNOWN_EVENT                            = 0;
      public static final int    START_EVENT_V3                           = 1;
      public static final int    QUERY_EVENT                              = 2;
      public static final int    STOP_EVENT                               = 3;
      public static final int    ROTATE_EVENT                             = 4;
      public static final int    INTVAR_EVENT                             = 5;
      public static final int    LOAD_EVENT                               = 6;
      public static final int    SLAVE_EVENT                              = 7;
      public static final int    CREATE_FILE_EVENT                        = 8;
      public static final int    APPEND_BLOCK_EVENT                       = 9;
      public static final int    EXEC_LOAD_EVENT                          = 10;
      public static final int    DELETE_FILE_EVENT                        = 11;
  
      /**
       * NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer sql_ex,
       * allowing multibyte TERMINATED BY etc; both types share the same class
       * (Load_log_event)
       */
      public static final int    NEW_LOAD_EVENT                           = 12;
      public static final int    RAND_EVENT                               = 13;
      public static final int    USER_VAR_EVENT                           = 14;
      public static final int    FORMAT_DESCRIPTION_EVENT                 = 15;
      public static final int    XID_EVENT                                = 16;
      public static final int    BEGIN_LOAD_QUERY_EVENT                   = 17;
      public static final int    EXECUTE_LOAD_QUERY_EVENT                 = 18;
  
      public static final int    TABLE_MAP_EVENT                          = 19;
  
      /**
       * These event numbers were used for 5.1.0 to 5.1.15 and are therefore
       * obsolete.
       */
      public static final int    PRE_GA_WRITE_ROWS_EVENT                  = 20;
      public static final int    PRE_GA_UPDATE_ROWS_EVENT                 = 21;
      public static final int    PRE_GA_DELETE_ROWS_EVENT                 = 22;
  
      /**
       * These event numbers are used from 5.1.16 and forward
       */
      public static final int    WRITE_ROWS_EVENT_V1                      = 23;
      public static final int    UPDATE_ROWS_EVENT_V1                     = 24;
      public static final int    DELETE_ROWS_EVENT_V1                     = 25;
  
      /**
       * Something out of the ordinary happened on the master
       */
      public static final int    INCIDENT_EVENT                           = 26;
  
      /**
       * Heartbeat event to be send by master at its idle time to ensure master's
       * online status to slave
       */
      public static final int    HEARTBEAT_LOG_EVENT                      = 27;
  
      /**
       * In some situations, it is necessary to send over ignorable data to the
       * slave: data that a slave can handle in case there is code for handling
       * it, but which can be ignored if it is not recognized.
       */
      public static final int    IGNORABLE_LOG_EVENT                      = 28;
      public static final int    ROWS_QUERY_LOG_EVENT                     = 29;
  
      /** Version 2 of the Row events */
      public static final int    WRITE_ROWS_EVENT                         = 30;
      public static final int    UPDATE_ROWS_EVENT                        = 31;
      public static final int    DELETE_ROWS_EVENT                        = 32;
  
      public static final int    GTID_LOG_EVENT                           = 33;
      public static final int    ANONYMOUS_GTID_LOG_EVENT                 = 34;
  
      public static final int    PREVIOUS_GTIDS_LOG_EVENT                 = 35;
  
      /* MySQL 5.7 events */
      public static final int    TRANSACTION_CONTEXT_EVENT                = 36;
  
      public static final int    VIEW_CHANGE_EVENT                        = 37;
  
      /* Prepared XA transaction terminal event similar to Xid */
      public static final int    XA_PREPARE_LOG_EVENT                     = 38;
  
      /**
       * Extension of UPDATE_ROWS_EVENT, allowing partial values according to
       * binlog_row_value_options.
       */
      public static final int    PARTIAL_UPDATE_ROWS_EVENT                = 39;
  
      /* mysql 8.0.20 */
      public static final int    TRANSACTION_PAYLOAD_EVENT                = 40;
  
      /* mysql 8.0.26 */
      public static final int    HEARTBEAT_LOG_EVENT_V2                   = 41;
  
      public static final int    MYSQL_ENUM_END_EVENT                     = 42;
  
      // mariaDb 5.5.34
      /* New MySQL/Sun events are to be added right above this comment */
      public static final int    MYSQL_EVENTS_END                         = 49;
  
      // PolarDB-X 2.5.0
      // CONSENSUS EVENTS START
      public static final int    CONSENSUS_LOG_EVENT                      = 101;
      public static final int    PREVIOUS_CONSENSUS_INDEX_LOG_EVENT       = 102;
      public static final int    CONSENSUS_CLUSTER_INFO_EVENT             = 103;
      public static final int    CONSENSUS_EMPTY_EVENT                    = 104;
      public static final int    GCN_LOG_EVENT                            = 105;
      // CONSENSUS EVENTS END
  
      public static final int    MARIA_EVENTS_BEGIN                       = 160;
      /* New Maria event numbers start from here */
      public static final int    ANNOTATE_ROWS_EVENT                      = 160;
      /*
       * Binlog checkpoint event. Used for XA crash recovery on the master, not
       * used in replication. A binlog checkpoint event specifies a binlog file
       * such that XA crash recovery can start from that file - and it is
       * guaranteed to find all XIDs that are prepared in storage engines but not
       * yet committed.
       */
      public static final int    BINLOG_CHECKPOINT_EVENT                  = 161;
      /*
       * Gtid event. For global transaction ID, used to start a new event group,
       * instead of the old BEGIN query event, and also to mark stand-alone
       * events.
       */
      public static final int    GTID_EVENT                               = 162;
      /*
       * Gtid list event. Logged at the start of every binlog, to record the
       * current replication state. This consists of the last GTID seen for each
       * replication domain.
       */
      public static final int    GTID_LIST_EVENT                          = 163;
  
      public static final int    START_ENCRYPTION_EVENT                   = 164;
  
      // mariadb 10.10.1
      /*
       * Compressed binlog event. Note that the order between WRITE/UPDATE/DELETE
       * events is significant; this is so that we can convert from the compressed to
       * the uncompressed event type with (type-WRITE_ROWS_COMPRESSED_EVENT +
       * WRITE_ROWS_EVENT) and similar for _V1.
       */
      public static final int    QUERY_COMPRESSED_EVENT                   = 165;
      public static final int    WRITE_ROWS_COMPRESSED_EVENT_V1           = 166;
      public static final int    UPDATE_ROWS_COMPRESSED_EVENT_V1          = 167;
      public static final int    DELETE_ROWS_COMPRESSED_EVENT_V1          = 168;
      public static final int    WRITE_ROWS_COMPRESSED_EVENT              = 169;
      public static final int    UPDATE_ROWS_COMPRESSED_EVENT             = 170;
      public static final int    DELETE_ROWS_COMPRESSED_EVENT             = 171;
  
      /** end marker */
      public static final int    ENUM_END_EVENT                           = 172;
  
      /**
       * 1 byte length, 1 byte format Length is total length in bytes, including 2
       * byte header Length values 0 and 1 are currently invalid and reserved.
       */
      public static final int    EXTRA_ROW_INFO_LEN_OFFSET                = 0;
      public static final int    EXTRA_ROW_INFO_FORMAT_OFFSET             = 1;
      public static final int    EXTRA_ROW_INFO_HDR_BYTES                 = 2;
      public static final int    EXTRA_ROW_INFO_MAX_PAYLOAD               = (255 - EXTRA_ROW_INFO_HDR_BYTES);
  
      // Events are without checksum though its generator
      public static final int    BINLOG_CHECKSUM_ALG_OFF                  = 0;
      // is checksum-capable New Master (NM).
      // CRC32 of zlib algorithm.
      public static final int    BINLOG_CHECKSUM_ALG_CRC32                = 1;
      // the cut line: valid alg range is [1, 0x7f].
      public static final int    BINLOG_CHECKSUM_ALG_ENUM_END             = 2;
      // special value to tag undetermined yet checksum
      public static final int    BINLOG_CHECKSUM_ALG_UNDEF                = 255;
      // or events from checksum-unaware servers
  
      public static final int    CHECKSUM_CRC32_SIGNATURE_LEN             = 4;
      public static final int    BINLOG_CHECKSUM_ALG_DESC_LEN             = 1;
      /**
       * defined statically while there is just one alg implemented
       */
      public static final int    BINLOG_CHECKSUM_LEN                      = CHECKSUM_CRC32_SIGNATURE_LEN;
  
      /* MySQL or old MariaDB slave with no announced capability. */
      public static final int    MARIA_SLAVE_CAPABILITY_UNKNOWN           = 0;
  
      /* MariaDB >= 5.3, which understands ANNOTATE_ROWS_EVENT. */
      public static final int    MARIA_SLAVE_CAPABILITY_ANNOTATE          = 1;
      /*
       * MariaDB >= 5.5. This version has the capability to tolerate events
       * omitted from the binlog stream without breaking replication (MySQL slaves
       * fail because they mis-compute the offsets into the master's binlog).
       */
      public static final int    MARIA_SLAVE_CAPABILITY_TOLERATE_HOLES    = 2;
      /* MariaDB >= 10.0, which knows about binlog_checkpoint_log_event. */
      public static final int    MARIA_SLAVE_CAPABILITY_BINLOG_CHECKPOINT = 3;
      /* MariaDB >= 10.0.1, which knows about global transaction id events. */
      public static final int    MARIA_SLAVE_CAPABILITY_GTID              = 4;
  
      /* Our capability. */
      public static final int    MARIA_SLAVE_CAPABILITY_MINE              = MARIA_SLAVE_CAPABILITY_GTID;
  
      /**
       * For an event, 'e', carrying a type code, that a slave, 's', does not
       * recognize, 's' will check 'e' for LOG_EVENT_IGNORABLE_F, and if the flag
       * is set, then 'e' is ignored. Otherwise, 's' acknowledges that it has
       * found an unknown event in the relay log.
       */
      public static final int    LOG_EVENT_IGNORABLE_F                    = 0x80;
  
      /** enum_field_types */
      public static final int    MYSQL_TYPE_DECIMAL                       = 0;
      public static final int    MYSQL_TYPE_TINY                          = 1;
      public static final int    MYSQL_TYPE_SHORT                         = 2;
      public static final int    MYSQL_TYPE_LONG                          = 3;
      public static final int    MYSQL_TYPE_FLOAT                         = 4;
      public static final int    MYSQL_TYPE_DOUBLE                        = 5;
      public static final int    MYSQL_TYPE_NULL                          = 6;
      public static final int    MYSQL_TYPE_TIMESTAMP                     = 7;
      public static final int    MYSQL_TYPE_LONGLONG                      = 8;
      public static final int    MYSQL_TYPE_INT24                         = 9;
      public static final int    MYSQL_TYPE_DATE                          = 10;
      public static final int    MYSQL_TYPE_TIME                          = 11;
      public static final int    MYSQL_TYPE_DATETIME                      = 12;
      public static final int    MYSQL_TYPE_YEAR                          = 13;
      public static final int    MYSQL_TYPE_NEWDATE                       = 14;
      public static final int    MYSQL_TYPE_VARCHAR                       = 15;
      public static final int    MYSQL_TYPE_BIT                           = 16;
      public static final int    MYSQL_TYPE_TIMESTAMP2                    = 17;
      public static final int    MYSQL_TYPE_DATETIME2                     = 18;
      public static final int    MYSQL_TYPE_TIME2                         = 19;
      public static final int    MYSQL_TYPE_TYPED_ARRAY                   = 20;
      public static final int    MYSQL_TYPE_INVALID                       = 243;
      public static final int    MYSQL_TYPE_BOOL                          = 244;
      public static final int    MYSQL_TYPE_JSON                          = 245;
      public static final int    MYSQL_TYPE_NEWDECIMAL                    = 246;
      public static final int    MYSQL_TYPE_ENUM                          = 247;
      public static final int    MYSQL_TYPE_SET                           = 248;
      public static final int    MYSQL_TYPE_TINY_BLOB                     = 249;
      public static final int    MYSQL_TYPE_MEDIUM_BLOB                   = 250;
      public static final int    MYSQL_TYPE_LONG_BLOB                     = 251;
      public static final int    MYSQL_TYPE_BLOB                          = 252;
      public static final int    MYSQL_TYPE_VAR_STRING                    = 253;
      public static final int    MYSQL_TYPE_STRING                        = 254;
      public static final int    MYSQL_TYPE_GEOMETRY                      = 255;
  
      public static String getTypeName(final int type) {
          switch (type) {
              case START_EVENT_V3:
                  return "Start_v3";
              case STOP_EVENT:
                  return "Stop";
              case QUERY_EVENT:
                  return "Query";
              case ROTATE_EVENT:
                  return "Rotate";
              case INTVAR_EVENT:
                  return "Intvar";
              case LOAD_EVENT:
                  return "Load";
              case NEW_LOAD_EVENT:
                  return "New_load";
              case SLAVE_EVENT:
                  return "Slave";
              case CREATE_FILE_EVENT:
                  return "Create_file";
              case APPEND_BLOCK_EVENT:
                  return "Append_block";
              case DELETE_FILE_EVENT:
                  return "Delete_file";
              case EXEC_LOAD_EVENT:
                  return "Exec_load";
              case RAND_EVENT:
                  return "RAND";
              case XID_EVENT:
                  return "Xid";
              case USER_VAR_EVENT:
                  return "User var";
              case FORMAT_DESCRIPTION_EVENT:
                  return "Format_desc";
              case TABLE_MAP_EVENT:
                  return "Table_map";
              case PRE_GA_WRITE_ROWS_EVENT:
                  return "Write_rows_event_old";
              case PRE_GA_UPDATE_ROWS_EVENT:
                  return "Update_rows_event_old";
              case PRE_GA_DELETE_ROWS_EVENT:
                  return "Delete_rows_event_old";
              case WRITE_ROWS_EVENT_V1:
                  return "Write_rows_v1";
              case UPDATE_ROWS_EVENT_V1:
                  return "Update_rows_v1";
              case DELETE_ROWS_EVENT_V1:
                  return "Delete_rows_v1";
              case BEGIN_LOAD_QUERY_EVENT:
                  return "Begin_load_query";
              case EXECUTE_LOAD_QUERY_EVENT:
                  return "Execute_load_query";
              case INCIDENT_EVENT:
                  return "Incident";
              case HEARTBEAT_LOG_EVENT:
              case HEARTBEAT_LOG_EVENT_V2:
                  return "Heartbeat";
              case IGNORABLE_LOG_EVENT:
                  return "Ignorable";
              case ROWS_QUERY_LOG_EVENT:
                  return "Rows_query";
              case WRITE_ROWS_EVENT:
                  return "Write_rows";
              case UPDATE_ROWS_EVENT:
                  return "Update_rows";
              case DELETE_ROWS_EVENT:
                  return "Delete_rows";
              case GTID_LOG_EVENT:
                  return "Gtid";
              case ANONYMOUS_GTID_LOG_EVENT:
                  return "Anonymous_Gtid";
              case PREVIOUS_GTIDS_LOG_EVENT:
                  return "Previous_gtids";
              case PARTIAL_UPDATE_ROWS_EVENT:
                  return "Update_rows_partial";
              case TRANSACTION_CONTEXT_EVENT :
                  return "Transaction_context";
              case VIEW_CHANGE_EVENT :
                  return "view_change";
              case XA_PREPARE_LOG_EVENT :
                  return "Xa_prepare";
              case TRANSACTION_PAYLOAD_EVENT :
                  return "transaction_payload";
              case CONSENSUS_LOG_EVENT:
                  return "Consensus_log";
              case PREVIOUS_CONSENSUS_INDEX_LOG_EVENT:
                  return "Previous_consensus_index";
              case CONSENSUS_CLUSTER_INFO_EVENT:
                  return "Consensus_cluster_info";
              case CONSENSUS_EMPTY_EVENT:
                  return "Consensus_empty";
              case GCN_LOG_EVENT:
                  return "Gcn_log";
              default:
                  return "Unknown type:" + type;
          }
      }
  
      protected static final Log logger = LogFactory.getLog(LogEvent.class);
  
      protected final LogHeader  header;
  
      /**
       * mysql半同步semi标识
       * 
       * <pre>
       * 0不需要semi ack 给mysql
       * 1需要semi ack给mysql
       * </pre>
       */
      protected int              semival;
  
      public int getSemival() {
          return semival;
      }
  
      public void setSemival(int semival) {
          this.semival = semival;
      }
  
      protected LogEvent(LogHeader header){
          this.header = header;
      }
  
      /**
       * Return event header.
       */
      public final LogHeader getHeader() {
          return header;
      }
  
      /**
       * The total size of this event, in bytes. In other words, this is the sum
       * of the sizes of Common-Header, Post-Header, and Body.
       */
      public final int getEventLen() {
          return header.getEventLen();
      }
  
      /**
       * Server ID of the server that created the event.
       */
      public final long getServerId() {
          return header.getServerId();
      }
  
      /**
       * The position of the next event in the master binary log, in bytes from
       * the beginning of the file. In a binlog that is not a relay log, this is
       * just the position of the next event, in bytes from the beginning of the
       * file. In a relay log, this is the position of the next event in the
       * master's binlog.
       */
      public final long getLogPos() {
          return header.getLogPos();
      }
  
      /**
       * The time when the query started, in seconds since 1970.
       */
      public final long getWhen() {
          return header.getWhen();
      }
  
  }
  