Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid string formatting during gtid event data deserialization and st… #101

Merged
merged 2 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public X509Certificate[] getAcceptedIssuers() {
private boolean gtidSetFallbackToPurged;
private boolean gtidEnabled = false;
private boolean useBinlogFilenamePositionInGtidMode;
protected String gtid;
protected Object gtid;
private boolean tx;

private EventDeserializer eventDeserializer = new EventDeserializer();
Expand Down Expand Up @@ -1131,7 +1131,7 @@ protected void updateGtidSet(Event event) {
switch(eventHeader.getEventType()) {
case GTID:
GtidEventData gtidEventData = (GtidEventData) EventDataWrapper.internal(event.getData());
gtid = gtidEventData.getGtid();
gtid = gtidEventData.getMySqlGtid();
break;
case XID:
commitGtid();
Expand Down Expand Up @@ -1183,7 +1183,7 @@ protected void commitGtid(String sql) {
private void commitGtid() {
if (gtid != null) {
synchronized (gtidSetAccessLock) {
gtidSet.add(gtid);
gtidSet.addGtid(gtid);
}
}
}
Expand Down
63 changes: 40 additions & 23 deletions src/main/java/com/github/shyiko/mysql/binlog/GtidSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,9 @@
*/
package com.github.shyiko.mysql.binlog;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.github.shyiko.mysql.binlog.event.MySqlGtid;

import java.util.*;

/**
* GTID set as described in <a href="https://dev.mysql.com/doc/refman/5.6/en/replication-gtids-concepts.html">GTID
Expand All @@ -38,7 +34,7 @@
*/
public class GtidSet {

private final Map<String, UUIDSet> map = new LinkedHashMap<String, UUIDSet>();
private final Map<UUID, UUIDSet> map = new LinkedHashMap<UUID, UUIDSet>();

public static GtidSet parse(String gtidStr) {
if ( MariadbGtidSet.isMariaGtidSet(gtidStr) ) {
Expand All @@ -55,7 +51,7 @@ public GtidSet(String gtidSet) {
gtidSet.replace("\n", "").split(",");
for (String uuidSet : uuidSets) {
int uuidSeparatorIndex = uuidSet.indexOf(":");
String sourceId = uuidSet.substring(0, uuidSeparatorIndex);
UUID sourceId = UUID.fromString(uuidSet.substring(0, uuidSeparatorIndex));
List<Interval> intervals = new ArrayList<Interval>();
String[] rawIntervals = uuidSet.substring(uuidSeparatorIndex + 1).split(":");
for (String interval : rawIntervals) {
Expand Down Expand Up @@ -87,7 +83,7 @@ public Collection<UUIDSet> getUUIDSets() {
* @return the {@link UUIDSet} for the identified server, or {@code null} if there are no GTIDs from that server.
*/
public UUIDSet getUUIDSet(String uuid) {
return map.get(uuid);
return map.get(UUID.fromString(uuid));
}

/**
Expand All @@ -97,22 +93,33 @@ public UUIDSet getUUIDSet(String uuid) {
* or {@code null} if there are no UUIDSet for the given server.
*/
public UUIDSet putUUIDSet(UUIDSet uuidSet) {
return map.put(uuidSet.getUUID(), uuidSet);
return map.put(uuidSet.getServerId(), uuidSet);
}

/**
* @param gtid GTID ("source_id:transaction_id")
* @return whether or not gtid was added to the set (false if it was already there)
*/
public boolean add(String gtid) {
String[] split = gtid.split(":");
String sourceId = split[0];
long transactionId = Long.parseLong(split[1]);
UUIDSet uuidSet = map.get(sourceId);
return add(MySqlGtid.fromString(gtid));
}

public void addGtid(Object gtid) {
if (gtid instanceof MySqlGtid) {
add((MySqlGtid) gtid);
} else if (gtid instanceof String) {
add((String) gtid);
} else {
throw new IllegalArgumentException(gtid + " not supported");
}
}

private boolean add(MySqlGtid mySqlGtid) {
UUIDSet uuidSet = map.get(mySqlGtid.getServerId());
if (uuidSet == null) {
map.put(sourceId, uuidSet = new UUIDSet(sourceId, new ArrayList<Interval>()));
map.put(mySqlGtid.getServerId(), uuidSet = new UUIDSet(mySqlGtid.getServerId(), new ArrayList<Interval>()));
}
return uuidSet.add(transactionId);
return uuidSet.add(mySqlGtid.getTransactionId());
}

/**
Expand All @@ -133,7 +140,7 @@ public boolean isContainedWithin(GtidSet other) {
return true;
}
for (UUIDSet uuidSet : map.values()) {
UUIDSet thatSet = other.getUUIDSet(uuidSet.getUUID());
UUIDSet thatSet = other.map.get(uuidSet.getServerId());
if (!uuidSet.isContainedWithin(thatSet)) {
return false;
}
Expand Down Expand Up @@ -162,7 +169,7 @@ public boolean equals(Object obj) {
public String toString() {
List<String> gtids = new ArrayList<String>();
for (UUIDSet uuidSet : map.values()) {
gtids.add(uuidSet.getUUID() + ":" + join(uuidSet.intervals, ":"));
gtids.add(uuidSet.getServerId() + ":" + join(uuidSet.intervals, ":"));
}
return join(gtids, ",");
}
Expand All @@ -188,10 +195,14 @@ private static String join(Collection<?> o, String delimiter) {
*/
public static final class UUIDSet {

private String uuid;
private List<Interval> intervals;
private final UUID uuid;
private final List<Interval> intervals;

public UUIDSet(String uuid, List<Interval> intervals) {
this(UUID.fromString(uuid), intervals);
}

public UUIDSet(UUID uuid, List<Interval> intervals) {
this.uuid = uuid;
this.intervals = intervals;
if (intervals.size() > 1) {
Expand Down Expand Up @@ -265,10 +276,16 @@ private int findInterval(long v) {
* Get the UUID for the server that generated the GTIDs.
* @return the server's UUID; never null
*/
@Deprecated
public String getUUID() {
return uuid.toString();
}

public UUID getServerId() {
return uuid;
}


/**
* Get the intervals of transaction numbers.
* @return the immutable transaction intervals; never null
Expand All @@ -288,7 +305,7 @@ public boolean isContainedWithin(UUIDSet other) {
if (other == null) {
return false;
}
if (!this.getUUID().equalsIgnoreCase(other.getUUID())) {
if (!this.uuid.equals(other.uuid)) {
// not even the same server ...
return false;
}
Expand Down Expand Up @@ -326,7 +343,7 @@ public boolean equals(Object obj) {
}
if (obj instanceof UUIDSet) {
UUIDSet that = (UUIDSet) obj;
return this.getUUID().equalsIgnoreCase(that.getUUID()) &&
return this.uuid.equals(that.uuid) &&
this.getIntervals().equals(that.getIntervals());
}
return super.equals(obj);
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/github/shyiko/mysql/binlog/MariadbGtidSet.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.github.shyiko.mysql.binlog;

import com.github.shyiko.mysql.binlog.event.MySqlGtid;

import java.util.*;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -113,6 +115,16 @@ public boolean add(String gtid) {
return true;
}

public void addGtid(Object gtid) {
if (gtid instanceof MariaGtid) {
add((MariaGtid) gtid);
} else if (gtid instanceof String) {
add((String) gtid);
} else {
throw new IllegalArgumentException(gtid + " not supported");
}
}

public void add(MariaGtid gtid) {
positionMap.put(gtid.getDomainId(), gtid);
addToSeenSet(gtid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,37 @@ public class GtidEventData implements EventData {

public static final byte COMMIT_FLAG = 1;

private String gtid;
private MySqlGtid gtid;
private byte flags;

@Deprecated
public GtidEventData() {
}

public GtidEventData(MySqlGtid gtid, byte flags) {
this.gtid = gtid;
this.flags = flags;
}

@Deprecated
public String getGtid() {
return gtid;
return gtid.toString();
}

@Deprecated
public void setGtid(String gtid) {
this.gtid = gtid;
this.gtid = MySqlGtid.fromString(gtid);
}

public MySqlGtid getMySqlGtid() {
return gtid;
}

public byte getFlags() {
return flags;
}

@Deprecated
public void setFlags(byte flags) {
this.flags = flags;
}
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/github/shyiko/mysql/binlog/event/MySqlGtid.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.github.shyiko.mysql.binlog.event;

import java.util.UUID;

public class MySqlGtid {
private final UUID serverId;
private final long transactionId;

public MySqlGtid(UUID serverId, long transactionId) {
this.serverId = serverId;
this.transactionId = transactionId;
}

public static MySqlGtid fromString(String gtid) {
String[] split = gtid.split(":");
String sourceId = split[0];
long transactionId = Long.parseLong(split[1]);
return new MySqlGtid(UUID.fromString(sourceId), transactionId);
}

@Override
public String toString() {
return serverId.toString()+":"+transactionId;
}

public UUID getServerId() {
return serverId;
}

public long getTransactionId() {
return transactionId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
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 <a href="mailto:pprasse@actindo.de">Patrick Prasse</a>
Expand All @@ -26,27 +28,25 @@ public class GtidEventDataDeserializer implements EventDataDeserializer<GtidEven

@Override
public GtidEventData deserialize(ByteArrayInputStream inputStream) throws IOException {
GtidEventData eventData = new GtidEventData();
byte flags = (byte) inputStream.readInteger(1);
byte[] sid = inputStream.read(16);
long gno = inputStream.readLong(8);
eventData.setFlags(flags);
eventData.setGtid(byteArrayToHex(sid, 0, 4) + "-" +
byteArrayToHex(sid, 4, 2) + "-" +
byteArrayToHex(sid, 6, 2) + "-" +
byteArrayToHex(sid, 8, 2) + "-" +
byteArrayToHex(sid, 10, 6) + ":" +
String.format("%d", gno)
long sourceIdMostSignificantBits = readLongBigEndian(inputStream);
long sourceIdLeastSignificantBits = readLongBigEndian(inputStream);
long transactionId = inputStream.readLong(8);

return new GtidEventData(
new MySqlGtid(
new UUID(sourceIdMostSignificantBits, sourceIdLeastSignificantBits),
transactionId
),
flags
);
return eventData;
}

private String byteArrayToHex(byte[] a, int offset, int len) {
StringBuilder sb = new StringBuilder();
for (int idx = offset; idx < (offset + len) && idx < a.length; idx++) {
sb.append(String.format("%02x", a[idx] & 0xff));
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 sb.toString();
return result;
}

}