Skip to content

Commit b997145

Browse files
authored
ZOOKEEPER-4864: Fix bad format when dump MultiTxn in TxnLogToolkit (#2192)
Decode Txn to record and format the output with the record for better format.
1 parent 935b5f4 commit b997145

File tree

2 files changed

+77
-20
lines changed

2 files changed

+77
-20
lines changed

zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,18 @@
4949
import org.apache.jute.BinaryOutputArchive;
5050
import org.apache.jute.Record;
5151
import org.apache.zookeeper.ZooDefs;
52+
import org.apache.zookeeper.server.ByteBufferInputStream;
5253
import org.apache.zookeeper.server.ExitCode;
5354
import org.apache.zookeeper.server.Request;
5455
import org.apache.zookeeper.server.TxnLogEntry;
5556
import org.apache.zookeeper.server.util.LogChopper;
5657
import org.apache.zookeeper.server.util.SerializeUtils;
58+
import org.apache.zookeeper.txn.CheckVersionTxn;
5759
import org.apache.zookeeper.txn.CreateContainerTxn;
5860
import org.apache.zookeeper.txn.CreateTTLTxn;
5961
import org.apache.zookeeper.txn.CreateTxn;
62+
import org.apache.zookeeper.txn.DeleteTxn;
63+
import org.apache.zookeeper.txn.ErrorTxn;
6064
import org.apache.zookeeper.txn.MultiTxn;
6165
import org.apache.zookeeper.txn.SetDataTxn;
6266
import org.apache.zookeeper.txn.Txn;
@@ -315,7 +319,7 @@ private void printTxn(byte[] bytes, String prefix) throws IOException {
315319
* @return the formatted string
316320
*/
317321
// @VisibleForTesting
318-
static String getFormattedTxnStr(Record txn) {
322+
static String getFormattedTxnStr(Record txn) throws IOException {
319323
StringBuilder txnData = new StringBuilder();
320324
if (txn == null) {
321325
return txnData.toString();
@@ -338,6 +342,12 @@ static String getFormattedTxnStr(Record txn) {
338342
txnData.append(createTTLTxn.getPath() + "," + checkNullToEmpty(createTTLTxn.getData()))
339343
.append("," + createTTLTxn.getAcl() + "," + createTTLTxn.getParentCVersion())
340344
.append("," + createTTLTxn.getTtl());
345+
} else if (txn instanceof DeleteTxn) {
346+
DeleteTxn deleteTxn = ((DeleteTxn) txn);
347+
txnData.append(deleteTxn.getPath());
348+
} else if (txn instanceof CheckVersionTxn) {
349+
CheckVersionTxn checkVersionTxn = ((CheckVersionTxn) txn);
350+
txnData.append(checkVersionTxn.getPath()).append(",").append(checkVersionTxn.getVersion());
341351
} else if (txn instanceof MultiTxn) {
342352
MultiTxn multiTxn = ((MultiTxn) txn);
343353
List<Txn> txnList = multiTxn.getTxns();
@@ -351,7 +361,7 @@ static String getFormattedTxnStr(Record txn) {
351361
if (t.getType() == ZooDefs.OpCode.error) {
352362
txnData.append(ByteBuffer.wrap(t.getData()).getInt());
353363
} else {
354-
txnData.append(checkNullToEmpty(t.getData()));
364+
txnData.append(getFormattedTxnStr(deserializeSubTxn(t)));
355365
}
356366
}
357367
} else {
@@ -361,6 +371,40 @@ static String getFormattedTxnStr(Record txn) {
361371
return txnData.toString();
362372
}
363373

374+
private static Record deserializeSubTxn(Txn txn) throws IOException {
375+
Record record;
376+
switch (txn.getType()) {
377+
case ZooDefs.OpCode.create:
378+
case ZooDefs.OpCode.create2:
379+
record = new CreateTxn();
380+
break;
381+
case ZooDefs.OpCode.createTTL:
382+
record = new CreateTTLTxn();
383+
break;
384+
case ZooDefs.OpCode.createContainer:
385+
record = new CreateContainerTxn();
386+
break;
387+
case ZooDefs.OpCode.delete:
388+
case ZooDefs.OpCode.deleteContainer:
389+
record = new DeleteTxn();
390+
break;
391+
case ZooDefs.OpCode.setData:
392+
record = new SetDataTxn();
393+
break;
394+
case ZooDefs.OpCode.error:
395+
record = new ErrorTxn();
396+
break;
397+
case ZooDefs.OpCode.check:
398+
record = new CheckVersionTxn();
399+
break;
400+
default:
401+
throw new IOException("Unsupported Txn with type=" + txn.getType());
402+
}
403+
ByteBuffer bb = ByteBuffer.wrap(txn.getData());
404+
ByteBufferInputStream.byteBuffer2Record(bb, record);
405+
return record;
406+
}
407+
364408
private static String checkNullToEmpty(byte[] data) {
365409
if (data == null || data.length == 0) {
366410
return "";

zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/TxnLogToolkitTest.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,26 @@
3030
import java.io.IOException;
3131
import java.io.PrintStream;
3232
import java.nio.ByteBuffer;
33+
import java.nio.charset.StandardCharsets;
3334
import java.util.ArrayList;
3435
import java.util.List;
3536
import java.util.Scanner;
3637
import java.util.regex.Matcher;
3738
import java.util.regex.Pattern;
3839
import org.apache.commons.io.FileUtils;
3940
import org.apache.jute.BinaryOutputArchive;
41+
import org.apache.jute.Record;
4042
import org.apache.zookeeper.KeeperException;
43+
import org.apache.zookeeper.ZooDefs;
4144
import org.apache.zookeeper.test.ClientBase;
45+
import org.apache.zookeeper.txn.CheckVersionTxn;
46+
import org.apache.zookeeper.txn.CreateContainerTxn;
47+
import org.apache.zookeeper.txn.CreateTTLTxn;
48+
import org.apache.zookeeper.txn.CreateTxn;
49+
import org.apache.zookeeper.txn.DeleteTxn;
4250
import org.apache.zookeeper.txn.ErrorTxn;
4351
import org.apache.zookeeper.txn.MultiTxn;
52+
import org.apache.zookeeper.txn.SetDataTxn;
4453
import org.apache.zookeeper.txn.Txn;
4554
import org.junit.jupiter.api.AfterEach;
4655
import org.junit.jupiter.api.BeforeEach;
@@ -95,27 +104,31 @@ public void testInitMissingFile() throws FileNotFoundException, TxnLogToolkit.Tx
95104

96105
@Test
97106
public void testMultiTxnDecode() throws IOException {
98-
//MultiTxn with four ops, and the first op error.
107+
// MultiTxn with multi ops including errors
99108
List<Txn> txns = new ArrayList<>();
100-
int type = -1;
101-
for (int i = 0; i < 4; i++) {
102-
ErrorTxn txn;
103-
if (i == 0) {
104-
txn = new ErrorTxn(KeeperException.Code.NONODE.intValue());
105-
} else {
106-
txn = new ErrorTxn(KeeperException.Code.RUNTIMEINCONSISTENCY.intValue());
107-
}
108-
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
109-
BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
110-
txn.serialize(boa, "request");
111-
ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
112-
txns.add(new Txn(type, bb.array()));
113-
}
114-
}
109+
txns.add(newSubTxn(ZooDefs.OpCode.error, new ErrorTxn(KeeperException.Code.NONODE.intValue())));
110+
txns.add(newSubTxn(ZooDefs.OpCode.error, new ErrorTxn(KeeperException.Code.RUNTIMEINCONSISTENCY.intValue())));
111+
txns.add(newSubTxn(ZooDefs.OpCode.create, new CreateTxn("/test", "test-data".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, true, 1)));
112+
txns.add(newSubTxn(ZooDefs.OpCode.createContainer, new CreateContainerTxn("/test_container", "test-data".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, 2)));
113+
txns.add(newSubTxn(ZooDefs.OpCode.createTTL, new CreateTTLTxn("/test_container", "test-data".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, 2, 20)));
114+
txns.add(newSubTxn(ZooDefs.OpCode.setData, new SetDataTxn("/test_set_data", "test-data".getBytes(StandardCharsets.UTF_8), 4)));
115+
txns.add(newSubTxn(ZooDefs.OpCode.delete, new DeleteTxn("/test_delete")));
116+
txns.add(newSubTxn(ZooDefs.OpCode.check, new CheckVersionTxn("/test_check_version", 5)));
115117
MultiTxn multiTxn = new MultiTxn(txns);
116-
117118
String formattedTxnStr = TxnLogToolkit.getFormattedTxnStr(multiTxn);
118-
assertEquals("error:-101;error:-2;error:-2;error:-2", formattedTxnStr);
119+
assertEquals("error:-101;error:-2;create:/test,test-data,[31,s{'world,'anyone}\n"
120+
+ "],true,1;createContainer:/test_container,test-data,[31,s{'world,'anyone}\n"
121+
+ "],2;createTTL:/test_container,test-data,[31,s{'world,'anyone}\n"
122+
+ "],2,20;setData:/test_set_data,test-data,4;delete:/test_delete;check:/test_check_version,5", formattedTxnStr);
123+
}
124+
125+
private static Txn newSubTxn(int type, Record record) throws IOException {
126+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
127+
BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
128+
record.serialize(boa, "request");
129+
ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
130+
return new Txn(type, bb.array());
131+
}
119132
}
120133

121134
@Test

0 commit comments

Comments
 (0)