Forráskód Böngészése

ZOOKEEPER-3410: zkTxnLogToolkit.sh will throw the NPE and stop the process of formatting txn logs due to the data's content is null

- the data can be null,but the other fileds(`acl`,`version`,`ttl`)  cannot be `null`.  I also make the `printTxn` method more safer , surrounding it with `try-catch` in case of other unexpected NPEs.
- some test cases were included in the [JIRA](https://issues.apache.org/jira/browse/ZOOKEEPER-3410).
- more details in the [ZOOKEEPER-3410](https://issues.apache.org/jira/browse/ZOOKEEPER-3410)

Author: maoling <maoling199210191@sina.com>

Reviewers: eolivelli@apache.org, andor@apache.org

Closes #975 from maoling/ZOOKEEPER-3410 and squashes the following commits:

22405c636 [maoling] revert the logic about try-catch the printTxn() method
a84c37406 [maoling] set the charset:UTF8 & e.printStackTrace()
8cc034e2e [maoling] ZOOKEEPER-3410:./zkTxnLogToolkit.sh will throw the NPE and stop the process of formatting txn logs due to the data's content is null
maoling 5 éve
szülő
commit
433cf7e2b6

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

@@ -269,7 +269,7 @@ public class TxnLogToolkit implements Closeable {
     private void printTxn(byte[] bytes, String prefix) throws IOException {
     private void printTxn(byte[] bytes, String prefix) throws IOException {
         TxnHeader hdr = new TxnHeader();
         TxnHeader hdr = new TxnHeader();
         Record txn = SerializeUtils.deserializeTxn(bytes, hdr);
         Record txn = SerializeUtils.deserializeTxn(bytes, hdr);
-        String txnStr = getDataStrFromTxn(txn);
+        String txnStr = getFormattedTxnStr(txn);
         String txns = String.format("%s session 0x%s cxid 0x%s zxid 0x%s %s %s",
         String txns = String.format("%s session 0x%s cxid 0x%s zxid 0x%s %s %s",
                 DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG).format(new Date(hdr.getTime())),
                 DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG).format(new Date(hdr.getTime())),
                 Long.toHexString(hdr.getClientId()),
                 Long.toHexString(hdr.getClientId()),
@@ -288,31 +288,31 @@ public class TxnLogToolkit implements Closeable {
     }
     }
 
 
     /**
     /**
-     * get transaction log data string with node's data as a string
-     * @param txn
-     * @return
+     * get the formatted string from the txn.
+     * @param txn transaction log data
+     * @return the formatted string
      */
      */
-    private static String getDataStrFromTxn(Record txn) {
+    private static String getFormattedTxnStr(Record txn) throws IOException {
         StringBuilder txnData = new StringBuilder();
         StringBuilder txnData = new StringBuilder();
         if (txn == null) {
         if (txn == null) {
             return txnData.toString();
             return txnData.toString();
         }
         }
         if (txn instanceof CreateTxn) {
         if (txn instanceof CreateTxn) {
             CreateTxn createTxn = ((CreateTxn) txn);
             CreateTxn createTxn = ((CreateTxn) txn);
-            txnData.append(createTxn.getPath() + "," + new String(createTxn.getData()))
+            txnData.append(createTxn.getPath() + "," + checkNullToEmpty(createTxn.getData()))
                    .append("," + createTxn.getAcl() + "," + createTxn.getEphemeral())
                    .append("," + createTxn.getAcl() + "," + createTxn.getEphemeral())
                    .append("," + createTxn.getParentCVersion());
                    .append("," + createTxn.getParentCVersion());
         } else if (txn instanceof SetDataTxn) {
         } else if (txn instanceof SetDataTxn) {
             SetDataTxn setDataTxn = ((SetDataTxn) txn);
             SetDataTxn setDataTxn = ((SetDataTxn) txn);
-            txnData.append(setDataTxn.getPath() + "," + new String(setDataTxn.getData()))
+            txnData.append(setDataTxn.getPath() + "," + checkNullToEmpty(setDataTxn.getData()))
                    .append("," + setDataTxn.getVersion());
                    .append("," + setDataTxn.getVersion());
         } else if (txn instanceof CreateContainerTxn) {
         } else if (txn instanceof CreateContainerTxn) {
             CreateContainerTxn createContainerTxn = ((CreateContainerTxn) txn);
             CreateContainerTxn createContainerTxn = ((CreateContainerTxn) txn);
-            txnData.append(createContainerTxn.getPath() + "," + new String(createContainerTxn.getData()))
+            txnData.append(createContainerTxn.getPath() + "," + checkNullToEmpty(createContainerTxn.getData()))
                    .append("," + createContainerTxn.getAcl() + "," + createContainerTxn.getParentCVersion());
                    .append("," + createContainerTxn.getAcl() + "," + createContainerTxn.getParentCVersion());
         } else if (txn instanceof CreateTTLTxn) {
         } else if (txn instanceof CreateTTLTxn) {
             CreateTTLTxn createTTLTxn = ((CreateTTLTxn) txn);
             CreateTTLTxn createTTLTxn = ((CreateTTLTxn) txn);
-            txnData.append(createTTLTxn.getPath() + "," + new String(createTTLTxn.getData()))
+            txnData.append(createTTLTxn.getPath() + "," + checkNullToEmpty(createTTLTxn.getData()))
                    .append("," + createTTLTxn.getAcl() + "," + createTTLTxn.getParentCVersion())
                    .append("," + createTTLTxn.getAcl() + "," + createTTLTxn.getParentCVersion())
                    .append("," + createTTLTxn.getTtl());
                    .append("," + createTTLTxn.getTtl());
         } else if (txn instanceof MultiTxn) {
         } else if (txn instanceof MultiTxn) {
@@ -321,9 +321,9 @@ public class TxnLogToolkit implements Closeable {
             for (int i = 0; i < txnList.size(); i++ ) {
             for (int i = 0; i < txnList.size(); i++ ) {
                 Txn t = txnList.get(i);
                 Txn t = txnList.get(i);
                 if (i == 0) {
                 if (i == 0) {
-                    txnData.append(TraceFormatter.op2String(t.getType()) + ":" + new String(t.getData()));
+                    txnData.append(TraceFormatter.op2String(t.getType()) + ":" + checkNullToEmpty(t.getData()));
                 } else {
                 } else {
-                    txnData.append(";" + TraceFormatter.op2String(t.getType()) + ":" + new String(t.getData()));
+                    txnData.append(";" + TraceFormatter.op2String(t.getType()) + ":" + checkNullToEmpty(t.getData()));
                 }
                 }
             }
             }
         } else {
         } else {
@@ -332,7 +332,15 @@ public class TxnLogToolkit implements Closeable {
 
 
         return txnData.toString();
         return txnData.toString();
     }
     }
-    
+
+    private static String checkNullToEmpty(byte[] data) throws IOException {
+        if (data == null || data.length == 0) {
+            return "";
+        }
+
+        return new String(data, "UTF8");
+    }
+
     private void openTxnLogFile() throws FileNotFoundException {
     private void openTxnLogFile() throws FileNotFoundException {
         txnFis = new FileInputStream(txnLogFile);
         txnFis = new FileInputStream(txnLogFile);
         logStream = BinaryInputArchive.getArchive(txnFis);
         logStream = BinaryInputArchive.getArchive(txnFis);