Skip to content

Commit 68c0ec7

Browse files
author
Stanley Shyiko
committed
Fixed checksum detection (#256)
1 parent 689d472 commit 68c0ec7

File tree

5 files changed

+82
-36
lines changed

5 files changed

+82
-36
lines changed

src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/ChecksumType.java

+6
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,10 @@ public int getLength() {
3636
return length;
3737
}
3838

39+
private static final ChecksumType[] VALUES = values();
40+
41+
public static ChecksumType byOrdinal(int ordinal) {
42+
return VALUES[ordinal];
43+
}
44+
3945
}

src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/EventDeserializer.java

+72-32
Original file line numberDiff line numberDiff line change
@@ -210,43 +210,83 @@ public Event nextEvent(ByteArrayInputStream inputStream) throws IOException {
210210
return null;
211211
}
212212
EventHeader eventHeader = eventHeaderDeserializer.deserialize(inputStream);
213-
EventDataDeserializer eventDataDeserializer = getEventDataDeserializer(eventHeader.getEventType());
214-
if (eventHeader.getEventType() == EventType.FORMAT_DESCRIPTION && formatDescEventDataDeserializer != null) {
215-
eventDataDeserializer = formatDescEventDataDeserializer;
216-
checksumLength = 0;
217-
} else if (eventHeader.getEventType() == EventType.TABLE_MAP && tableMapEventDataDeserializer != null) {
218-
eventDataDeserializer = tableMapEventDataDeserializer;
213+
EventData eventData;
214+
switch (eventHeader.getEventType()) {
215+
case FORMAT_DESCRIPTION:
216+
eventData = deserializeFormatDescriptionEventData(inputStream, eventHeader);
217+
break;
218+
case TABLE_MAP:
219+
eventData = deserializeTableMapEventData(inputStream, eventHeader);
220+
break;
221+
default:
222+
EventDataDeserializer eventDataDeserializer = getEventDataDeserializer(eventHeader.getEventType());
223+
eventData = deserializeEventData(inputStream, eventHeader, eventDataDeserializer);
219224
}
220-
EventData eventData = deserializeEventData(inputStream, eventHeader, eventDataDeserializer);
221-
if (eventHeader.getEventType() == EventType.FORMAT_DESCRIPTION) {
222-
FormatDescriptionEventData formatDescriptionEvent;
223-
if (eventData instanceof EventDataWrapper) {
224-
EventDataWrapper eventDataWrapper = (EventDataWrapper) eventData;
225-
formatDescriptionEvent = (FormatDescriptionEventData) eventDataWrapper.getInternal();
226-
if (formatDescEventDataDeserializer != null) {
227-
eventData = eventDataWrapper.getExternal();
225+
return new Event(eventHeader, eventData);
226+
}
227+
228+
private EventData deserializeFormatDescriptionEventData(ByteArrayInputStream inputStream, EventHeader eventHeader)
229+
throws EventDataDeserializationException {
230+
EventDataDeserializer eventDataDeserializer =
231+
formatDescEventDataDeserializer != null ?
232+
formatDescEventDataDeserializer :
233+
getEventDataDeserializer(EventType.FORMAT_DESCRIPTION);
234+
int eventBodyLength = (int) eventHeader.getDataLength();
235+
EventData eventData;
236+
try {
237+
inputStream.enterBlock(eventBodyLength);
238+
try {
239+
eventData = eventDataDeserializer.deserialize(inputStream);
240+
// https://dev.mysql.com/worklog/task/?id=2540#tabs-2540-4
241+
// +-----------+------------+-----------+------------------------+----------+
242+
// | Header | Payload (dataLength) | Checksum Type (1 byte) | Checksum |
243+
// +-----------+------------+-----------+------------------------+----------+
244+
// | (eventBodyLength) |
245+
// +------------------------------------------------------------+
246+
FormatDescriptionEventData formatDescriptionEvent;
247+
if (eventData instanceof EventDataWrapper) {
248+
EventDataWrapper eventDataWrapper = (EventDataWrapper) eventData;
249+
formatDescriptionEvent = (FormatDescriptionEventData) eventDataWrapper.getInternal();
250+
if (formatDescEventDataDeserializer != null) {
251+
eventData = eventDataWrapper.getExternal();
252+
}
253+
} else {
254+
formatDescriptionEvent = (FormatDescriptionEventData) eventData;
228255
}
229-
} else {
230-
formatDescriptionEvent = (FormatDescriptionEventData) eventData;
231-
}
232-
if (eventHeader.getDataLength() != formatDescriptionEvent.getDataLength()) {
233-
// -1 byte to compensate for "checksum type" field
234-
checksumLength = (int) (eventHeader.getDataLength() - formatDescriptionEvent.getDataLength() - 1);
235-
}
236-
} else if (eventHeader.getEventType() == EventType.TABLE_MAP) {
237-
TableMapEventData tableMapEvent;
238-
if (eventData instanceof EventDataWrapper) {
239-
EventDataWrapper eventDataWrapper = (EventDataWrapper) eventData;
240-
tableMapEvent = (TableMapEventData) eventDataWrapper.getInternal();
241-
if (tableMapEventDataDeserializer != null) {
242-
eventData = eventDataWrapper.getExternal();
256+
int checksumBlockLength = eventBodyLength - formatDescriptionEvent.getDataLength();
257+
if (checksumBlockLength > 0) {
258+
inputStream.skip(inputStream.available() - checksumBlockLength);
259+
int checksumType = inputStream.read();
260+
checksumLength = ChecksumType.byOrdinal(checksumType).getLength();
243261
}
244-
} else {
245-
tableMapEvent = (TableMapEventData) eventData;
262+
} finally {
263+
inputStream.skipToTheEndOfTheBlock();
246264
}
247-
tableMapEventByTableId.put(tableMapEvent.getTableId(), tableMapEvent);
265+
} catch (IOException e) {
266+
throw new EventDataDeserializationException(eventHeader, e);
248267
}
249-
return new Event(eventHeader, eventData);
268+
return eventData;
269+
}
270+
271+
public EventData deserializeTableMapEventData(ByteArrayInputStream inputStream, EventHeader eventHeader)
272+
throws IOException {
273+
EventDataDeserializer eventDataDeserializer =
274+
tableMapEventDataDeserializer != null ?
275+
tableMapEventDataDeserializer :
276+
getEventDataDeserializer(EventType.TABLE_MAP);
277+
EventData eventData = deserializeEventData(inputStream, eventHeader, eventDataDeserializer);
278+
TableMapEventData tableMapEvent;
279+
if (eventData instanceof EventDataWrapper) {
280+
EventDataWrapper eventDataWrapper = (EventDataWrapper) eventData;
281+
tableMapEvent = (TableMapEventData) eventDataWrapper.getInternal();
282+
if (tableMapEventDataDeserializer != null) {
283+
eventData = eventDataWrapper.getExternal();
284+
}
285+
} else {
286+
tableMapEvent = (TableMapEventData) eventData;
287+
}
288+
tableMapEventByTableId.put(tableMapEvent.getTableId(), tableMapEvent);
289+
return eventData;
250290
}
251291

252292
private EventData deserializeEventData(ByteArrayInputStream inputStream, EventHeader eventHeader,

src/test/java/com/github/shyiko/mysql/binlog/BinaryLogFileReaderIntegrationTest.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ public void testNextEvent() throws Exception {
4848
@Test
4949
public void testChecksumNONE() throws Exception {
5050
EventDeserializer eventDeserializer = new EventDeserializer();
51-
BinaryLogFileReader reader = new BinaryLogFileReader(new GZIPInputStream(
52-
new FileInputStream("src/test/resources/mysql-bin.sakila.gz")), eventDeserializer);
53-
readAll(reader, 1462);
51+
BinaryLogFileReader reader = new BinaryLogFileReader(
52+
new FileInputStream("src/test/resources/mysql-bin.checksum-none"), eventDeserializer);
53+
readAll(reader, 191);
5454
}
5555

5656
@Test
5757
public void testChecksumCRC32() throws Exception {
5858
EventDeserializer eventDeserializer = new EventDeserializer();
5959
BinaryLogFileReader reader = new BinaryLogFileReader(
60-
new FileInputStream("src/test/resources/mysql-bin.000001"), eventDeserializer);
60+
new FileInputStream("src/test/resources/mysql-bin.checksum-crc32"), eventDeserializer);
6161
readAll(reader, 303);
6262
}
6363

36.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)