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

com.github.shyiko.mysql.binlog.event.deserialization.GtidEventDataDeserializer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013 Patrick Prasse
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.shyiko.mysql.binlog.event.deserialization;

import com.github.shyiko.mysql.binlog.event.GtidEventData;
import com.github.shyiko.mysql.binlog.event.MySqlGtid;
import com.github.shyiko.mysql.binlog.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.UUID;

/**
 * @author Patrick Prasse
 */
public class GtidEventDataDeserializer implements EventDataDeserializer {
    public static final int LOGICAL_TIMESTAMP_TYPECODE_LENGTH = 1;
    // Type code used before the logical timestamps.
    public static final int LOGICAL_TIMESTAMP_TYPECODE = 2;
    public static final int LOGICAL_TIMESTAMP_LENGTH = 8;
    // Length of immediate and original commit timestamps
    public static final int IMMEDIATE_COMMIT_TIMESTAMP_LENGTH = 7;
    public static final int ORIGINAL_COMMIT_TIMESTAMP_LENGTH = 7;
    // Use 7 bytes out of which 1 bit is used as a flag.
    public static final int ENCODED_COMMIT_TIMESTAMP_LENGTH = 55;
    public static final int TRANSACTION_LENGTH_MIN_LENGTH = 1;
    // Length of immediate and original server versions
    public static final int IMMEDIATE_SERVER_VERSION_LENGTH = 4;
    public static final int ORIGINAL_SERVER_VERSION_LENGTH = 4;
    // Use 4 bytes out of which 1 bit is used as a flag.
    public static final int ENCODED_SERVER_VERSION_LENGTH = 31;
    public static final int UNDEFINED_SERVER_VERSION = 999999;

    @Override
    public GtidEventData deserialize(ByteArrayInputStream inputStream) throws IOException {
        byte flags = (byte) inputStream.readInteger(1);
        long sourceIdMostSignificantBits = readLongBigEndian(inputStream);
        long sourceIdLeastSignificantBits = readLongBigEndian(inputStream);
        long transactionId = inputStream.readLong(8);

        final MySqlGtid gtid = new MySqlGtid(
                new UUID(sourceIdMostSignificantBits, sourceIdLeastSignificantBits),
                transactionId
            );

        // MTR logical clock
        long lastCommitted = 0;
        long sequenceNumber = 0;
        // ImmediateCommitTimestamp/OriginalCommitTimestamp are introduced in MySQL-8.0.1, see:
        // https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-1.html
        long immediateCommitTimestamp = 0;
        long originalCommitTimestamp = 0;
        // Total transaction length (including this GTIDEvent), introduced in MySQL-8.0.2, see:
        // https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-2.html
        long transactionLength = 0;
        // ImmediateServerVersion/OriginalServerVersion are introduced in MySQL-8.0.14, see
        // https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-14.html
        int immediateServerVersion = 0;
        int originalServerVersion = 0;

        // Logical timestamps - since MySQL 5.7.6
        if (inputStream.peek() == LOGICAL_TIMESTAMP_TYPECODE) {
            inputStream.skip(LOGICAL_TIMESTAMP_TYPECODE_LENGTH);
            lastCommitted = inputStream.readLong(LOGICAL_TIMESTAMP_LENGTH);
            sequenceNumber = inputStream.readLong(LOGICAL_TIMESTAMP_LENGTH);
            // Immediate and original commit timestamps are introduced in MySQL-8.0.1
            if (inputStream.available() >= IMMEDIATE_COMMIT_TIMESTAMP_LENGTH) {
                immediateCommitTimestamp = inputStream.readLong(IMMEDIATE_COMMIT_TIMESTAMP_LENGTH);
                // Check the MSB to determine how to populate the original commit timestamp
                if ((immediateCommitTimestamp & (1L << ENCODED_COMMIT_TIMESTAMP_LENGTH)) != 0) {
                    immediateCommitTimestamp &= ~(1L << ENCODED_COMMIT_TIMESTAMP_LENGTH);
                    originalCommitTimestamp = inputStream.readLong(ORIGINAL_COMMIT_TIMESTAMP_LENGTH);
                } else {
                    // Transaction originated in the previous server eg. writer if direct connect
                    originalCommitTimestamp = immediateCommitTimestamp;
                }
                // Total transaction length (including this GTIDEvent), introduced in MySQL-8.0.2
                if (inputStream.available() >= TRANSACTION_LENGTH_MIN_LENGTH) {
                    transactionLength = inputStream.readPackedLong();
                }
                immediateServerVersion = UNDEFINED_SERVER_VERSION;
                originalServerVersion = UNDEFINED_SERVER_VERSION;
                // Immediate and original server versions are introduced in MySQL-8.0.14
                if (inputStream.available() >= IMMEDIATE_SERVER_VERSION_LENGTH) {
                    immediateServerVersion = inputStream.readInteger(IMMEDIATE_SERVER_VERSION_LENGTH);
                    // Check the MSB to determine how to populate original server version
                    if ((immediateServerVersion & (1L << ENCODED_SERVER_VERSION_LENGTH)) != 0) {
                        immediateServerVersion &= ~(1L << ENCODED_SERVER_VERSION_LENGTH);
                        originalServerVersion = inputStream.readInteger(ORIGINAL_SERVER_VERSION_LENGTH);
                    } else {
                        originalServerVersion = immediateServerVersion;
                    }
                }
            }
        }

        return new GtidEventData(gtid, flags, lastCommitted, sequenceNumber, immediateCommitTimestamp, originalCommitTimestamp, transactionLength, immediateServerVersion, originalServerVersion);
    }

    private static long readLongBigEndian(ByteArrayInputStream input) throws IOException {
        long result = 0;
        for (int i = 0; i < 8; ++i) {
            result = ((result << 8) | (input.read() & 0xff));
        }
        return result;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy