This is an automated email from the ASF dual-hosted git repository. tison pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/master by this push: new b99714543 ZOOKEEPER-4864: Fix bad format when dump MultiTxn in TxnLogToolkit (#2192) b99714543 is described below commit b99714543db86ca081a5d648c565f0d9cb4c82c2 Author: Xin Luo <65529035+luoxi...@users.noreply.github.com> AuthorDate: Tue Oct 15 15:03:54 2024 +0800 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. --- .../server/persistence/TxnLogToolkit.java | 48 ++++++++++++++++++++- .../server/persistence/TxnLogToolkitTest.java | 49 ++++++++++++++-------- 2 files changed, 77 insertions(+), 20 deletions(-) diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java index 767d64077..8cd082122 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/TxnLogToolkit.java @@ -49,14 +49,18 @@ import org.apache.jute.BinaryInputArchive; import org.apache.jute.BinaryOutputArchive; import org.apache.jute.Record; import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.server.ByteBufferInputStream; import org.apache.zookeeper.server.ExitCode; import org.apache.zookeeper.server.Request; import org.apache.zookeeper.server.TxnLogEntry; import org.apache.zookeeper.server.util.LogChopper; import org.apache.zookeeper.server.util.SerializeUtils; +import org.apache.zookeeper.txn.CheckVersionTxn; import org.apache.zookeeper.txn.CreateContainerTxn; import org.apache.zookeeper.txn.CreateTTLTxn; import org.apache.zookeeper.txn.CreateTxn; +import org.apache.zookeeper.txn.DeleteTxn; +import org.apache.zookeeper.txn.ErrorTxn; import org.apache.zookeeper.txn.MultiTxn; import org.apache.zookeeper.txn.SetDataTxn; import org.apache.zookeeper.txn.Txn; @@ -315,7 +319,7 @@ public class TxnLogToolkit implements Closeable { * @return the formatted string */ // @VisibleForTesting - static String getFormattedTxnStr(Record txn) { + static String getFormattedTxnStr(Record txn) throws IOException { StringBuilder txnData = new StringBuilder(); if (txn == null) { return txnData.toString(); @@ -338,6 +342,12 @@ public class TxnLogToolkit implements Closeable { txnData.append(createTTLTxn.getPath() + "," + checkNullToEmpty(createTTLTxn.getData())) .append("," + createTTLTxn.getAcl() + "," + createTTLTxn.getParentCVersion()) .append("," + createTTLTxn.getTtl()); + } else if (txn instanceof DeleteTxn) { + DeleteTxn deleteTxn = ((DeleteTxn) txn); + txnData.append(deleteTxn.getPath()); + } else if (txn instanceof CheckVersionTxn) { + CheckVersionTxn checkVersionTxn = ((CheckVersionTxn) txn); + txnData.append(checkVersionTxn.getPath()).append(",").append(checkVersionTxn.getVersion()); } else if (txn instanceof MultiTxn) { MultiTxn multiTxn = ((MultiTxn) txn); List<Txn> txnList = multiTxn.getTxns(); @@ -351,7 +361,7 @@ public class TxnLogToolkit implements Closeable { if (t.getType() == ZooDefs.OpCode.error) { txnData.append(ByteBuffer.wrap(t.getData()).getInt()); } else { - txnData.append(checkNullToEmpty(t.getData())); + txnData.append(getFormattedTxnStr(deserializeSubTxn(t))); } } } else { @@ -361,6 +371,40 @@ public class TxnLogToolkit implements Closeable { return txnData.toString(); } + private static Record deserializeSubTxn(Txn txn) throws IOException { + Record record; + switch (txn.getType()) { + case ZooDefs.OpCode.create: + case ZooDefs.OpCode.create2: + record = new CreateTxn(); + break; + case ZooDefs.OpCode.createTTL: + record = new CreateTTLTxn(); + break; + case ZooDefs.OpCode.createContainer: + record = new CreateContainerTxn(); + break; + case ZooDefs.OpCode.delete: + case ZooDefs.OpCode.deleteContainer: + record = new DeleteTxn(); + break; + case ZooDefs.OpCode.setData: + record = new SetDataTxn(); + break; + case ZooDefs.OpCode.error: + record = new ErrorTxn(); + break; + case ZooDefs.OpCode.check: + record = new CheckVersionTxn(); + break; + default: + throw new IOException("Unsupported Txn with type=" + txn.getType()); + } + ByteBuffer bb = ByteBuffer.wrap(txn.getData()); + ByteBufferInputStream.byteBuffer2Record(bb, record); + return record; + } + private static String checkNullToEmpty(byte[] data) { if (data == null || data.length == 0) { return ""; diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/TxnLogToolkitTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/TxnLogToolkitTest.java index ec02c75b3..361666709 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/TxnLogToolkitTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/TxnLogToolkitTest.java @@ -30,6 +30,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintStream; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Scanner; @@ -37,10 +38,18 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.FileUtils; import org.apache.jute.BinaryOutputArchive; +import org.apache.jute.Record; import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.test.ClientBase; +import org.apache.zookeeper.txn.CheckVersionTxn; +import org.apache.zookeeper.txn.CreateContainerTxn; +import org.apache.zookeeper.txn.CreateTTLTxn; +import org.apache.zookeeper.txn.CreateTxn; +import org.apache.zookeeper.txn.DeleteTxn; import org.apache.zookeeper.txn.ErrorTxn; import org.apache.zookeeper.txn.MultiTxn; +import org.apache.zookeeper.txn.SetDataTxn; import org.apache.zookeeper.txn.Txn; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -95,27 +104,31 @@ public class TxnLogToolkitTest { @Test public void testMultiTxnDecode() throws IOException { - //MultiTxn with four ops, and the first op error. + // MultiTxn with multi ops including errors List<Txn> txns = new ArrayList<>(); - int type = -1; - for (int i = 0; i < 4; i++) { - ErrorTxn txn; - if (i == 0) { - txn = new ErrorTxn(KeeperException.Code.NONODE.intValue()); - } else { - txn = new ErrorTxn(KeeperException.Code.RUNTIMEINCONSISTENCY.intValue()); - } - try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos); - txn.serialize(boa, "request"); - ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray()); - txns.add(new Txn(type, bb.array())); - } - } + txns.add(newSubTxn(ZooDefs.OpCode.error, new ErrorTxn(KeeperException.Code.NONODE.intValue()))); + txns.add(newSubTxn(ZooDefs.OpCode.error, new ErrorTxn(KeeperException.Code.RUNTIMEINCONSISTENCY.intValue()))); + txns.add(newSubTxn(ZooDefs.OpCode.create, new CreateTxn("/test", "test-data".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, true, 1))); + txns.add(newSubTxn(ZooDefs.OpCode.createContainer, new CreateContainerTxn("/test_container", "test-data".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, 2))); + txns.add(newSubTxn(ZooDefs.OpCode.createTTL, new CreateTTLTxn("/test_container", "test-data".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, 2, 20))); + txns.add(newSubTxn(ZooDefs.OpCode.setData, new SetDataTxn("/test_set_data", "test-data".getBytes(StandardCharsets.UTF_8), 4))); + txns.add(newSubTxn(ZooDefs.OpCode.delete, new DeleteTxn("/test_delete"))); + txns.add(newSubTxn(ZooDefs.OpCode.check, new CheckVersionTxn("/test_check_version", 5))); MultiTxn multiTxn = new MultiTxn(txns); - String formattedTxnStr = TxnLogToolkit.getFormattedTxnStr(multiTxn); - assertEquals("error:-101;error:-2;error:-2;error:-2", formattedTxnStr); + assertEquals("error:-101;error:-2;create:/test,test-data,[31,s{'world,'anyone}\n" + + "],true,1;createContainer:/test_container,test-data,[31,s{'world,'anyone}\n" + + "],2;createTTL:/test_container,test-data,[31,s{'world,'anyone}\n" + + "],2,20;setData:/test_set_data,test-data,4;delete:/test_delete;check:/test_check_version,5", formattedTxnStr); + } + + private static Txn newSubTxn(int type, Record record) throws IOException { + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos); + record.serialize(boa, "request"); + ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray()); + return new Txn(type, bb.array()); + } } @Test