Skip to content

Commit 7efa961

Browse files
committed
Backported "handling of packets exceeding 16mb in size" from master@26d6760
1 parent 153cce1 commit 7efa961

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

src/main/java/com/github/shyiko/mysql/binlog/BinaryLogClient.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.github.shyiko.mysql.binlog.network.SocketFactory;
3636
import com.github.shyiko.mysql.binlog.network.protocol.ErrorPacket;
3737
import com.github.shyiko.mysql.binlog.network.protocol.GreetingPacket;
38+
import com.github.shyiko.mysql.binlog.network.protocol.Packet;
3839
import com.github.shyiko.mysql.binlog.network.protocol.PacketChannel;
3940
import com.github.shyiko.mysql.binlog.network.protocol.ResultSetRowPacket;
4041
import com.github.shyiko.mysql.binlog.network.protocol.command.AuthenticateCommand;
@@ -73,6 +74,9 @@
7374
*/
7475
public class BinaryLogClient implements BinaryLogClientMXBean {
7576

77+
// https://dev.mysql.com/doc/internals/en/sending-more-than-16mbyte.html
78+
private static final int MAX_PACKET_LENGTH = 16777215;
79+
7680
private final Logger logger = Logger.getLogger(getClass().getName());
7781

7882
private final String hostname;
@@ -592,7 +596,9 @@ private void listenForEventPackets() throws IOException {
592596
}
593597
Event event;
594598
try {
595-
event = eventDeserializer.nextEvent(inputStream);
599+
event = eventDeserializer.nextEvent(packetLength == MAX_PACKET_LENGTH ?
600+
new ByteArrayInputStream(readPacketSplitInChunks(inputStream, packetLength - 1)) :
601+
inputStream);
596602
} catch (Exception e) {
597603
Throwable cause = e instanceof EventDataDeserializationException ? e.getCause() : e;
598604
if (cause instanceof EOFException || cause instanceof SocketException) {
@@ -628,6 +634,18 @@ private void listenForEventPackets() throws IOException {
628634
}
629635
}
630636

637+
private byte[] readPacketSplitInChunks(ByteArrayInputStream inputStream, int packetLength) throws IOException {
638+
byte[] result = inputStream.read(packetLength);
639+
int chunkLength;
640+
do {
641+
chunkLength = inputStream.readInteger(3);
642+
inputStream.skip(1); // 1 byte for sequence
643+
result = Arrays.copyOf(result, result.length + chunkLength);
644+
inputStream.fill(result, result.length - chunkLength, chunkLength);
645+
} while (chunkLength == Packet.MAX_LENGTH);
646+
return result;
647+
}
648+
631649
private void updateClientBinlogFilenameAndPosition(Event event) {
632650
EventHeader eventHeader = event.getHeader();
633651
if (eventHeader.getEventType() == EventType.ROTATE) {

src/main/java/com/github/shyiko/mysql/binlog/io/ByteArrayInputStream.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,20 @@ public String readZeroTerminatedString() throws IOException {
8484
return new String(s.toByteArray());
8585
}
8686

87-
/**
88-
* Alias for read(result, 0, length).
89-
*/
9087
public byte[] read(int length) throws IOException {
9188
byte[] bytes = new byte[length];
92-
read(bytes, 0, length);
89+
fill(bytes, 0, length);
9390
return bytes;
9491
}
9592

93+
public void fill(byte[] bytes, int offset, int length) throws IOException {
94+
int remaining = length;
95+
while (remaining != 0) {
96+
int read = read(bytes, offset + length - remaining, remaining);
97+
remaining -= read;
98+
}
99+
}
100+
96101
public BitSet readBitSet(int length, boolean bigEndian) throws IOException {
97102
// according to MySQL internals the amount of storage required for N columns is INT((N+7)/8) bytes
98103
byte[] bytes = read((length + 7) >> 3);

src/main/java/com/github/shyiko/mysql/binlog/network/protocol/Packet.java

+2
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@
2020
*/
2121
public interface Packet {
2222

23+
// https://dev.mysql.com/doc/internals/en/sending-more-than-16mbyte.html
24+
int MAX_LENGTH = 16777215;
2325
}

supplement/codequality/checkstyle.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
<property name="protectedAllowed" value="true"/>
122122
</module>
123123
<module name="FinalClass"/>
124-
<module name="InterfaceIsType"/>
124+
<!--<module name="InterfaceIsType"/>-->
125125
<module name="HideUtilityClassConstructor"/>
126126
<module name="ThrowsCount">
127127
<property name="max" value="3"/>

0 commit comments

Comments
 (0)