Explorar o código

ZOOKEEPER-1069: Calling shutdown() on a QuorumPeer too quickly can lead to a corrupt log

git-svn-id: https://svn.apache.org/repos/asf/zookeeper/trunk@1132489 13f79535-47bb-0310-9956-ffa450edef68
Camille Fournier %!s(int64=14) %!d(string=hai) anos
pai
achega
b916b3bbb6

+ 2 - 0
CHANGES.txt

@@ -216,6 +216,8 @@ BUGFIXES:
   ZOOKEEPER-1058. fix typo in opToString for getData. (camille)
   
   ZOOKEEPER-1046. Creating a new sequential node results in a ZNODEEXISTS error. (Vishal K via camille) 
+  
+  ZOOKEEPER-1069. Calling shutdown() on a QuorumPeer too quickly can lead to a corrupt log. (Vishal K via camille) 
 
 IMPROVEMENTS:
   ZOOKEEPER-724. Improve junit test integration - log harness information 

+ 2 - 0
src/java/main/org/apache/zookeeper/server/persistence/FileTxnLog.java

@@ -206,6 +206,8 @@ public class FileTxnLog implements TxnLog {
                oa = BinaryOutputArchive.getArchive(logStream);
                FileHeader fhdr = new FileHeader(TXNLOG_MAGIC,VERSION, dbId);
                fhdr.serialize(oa, "fileheader");
+               // Make sure that the magic number is written before padding.
+               logStream.flush();
                currentSize = fos.getChannel().position();
                streamsToFlush.add(fos);
             }

+ 25 - 0
src/java/test/org/apache/zookeeper/test/LoadFromLogTest.java

@@ -46,6 +46,9 @@ import org.apache.zookeeper.txn.DeleteTxn;
 import org.apache.zookeeper.txn.TxnHeader;
 import org.apache.zookeeper.ZooDefs.OpCode;
 import org.apache.jute.Record;
+import java.io.FileInputStream;
+import org.apache.jute.BinaryInputArchive;
+import org.apache.zookeeper.server.persistence.FileHeader;
 
 public class LoadFromLogTest extends ZKTestCase implements  Watcher {
     private static String HOSTPORT = "127.0.0.1:" + PortAssignment.unique();
@@ -185,4 +188,26 @@ public class LoadFromLogTest extends ZKTestCase implements  Watcher {
                 newCversion + ", " + newPzxid + ">",
                 (newCversion == prevCversion + 1 && newPzxid == prevPzxid + 1));
     }
+    /**
+     * Simulates ZOOKEEPER-1069 and verifies that flush() before padLogFile
+     * fixes it.
+     */
+    @Test
+    public void testPad() throws Exception {
+        File tmpDir = ClientBase.createTmpDir();
+        FileTxnLog txnLog = new FileTxnLog(tmpDir);
+        TxnHeader txnHeader = new TxnHeader(0xabcd, 0x123, 0x123,
+              System.currentTimeMillis(), OpCode.create);
+        Record txn = new CreateTxn("/Test", new byte[0], null, false);
+        txnLog.append(txnHeader, txn);
+        FileInputStream in = new FileInputStream(tmpDir.getPath() + "/log." +
+              Long.toHexString(txnHeader.getZxid()));
+        BinaryInputArchive ia  = BinaryInputArchive.getArchive(in);
+        FileHeader header = new FileHeader();
+        header.deserialize(ia, "fileheader");
+        LOG.info("Expected header :" + header.getMagic() +
+              " Received : " + FileTxnLog.TXNLOG_MAGIC);
+        Assert.assertTrue("Missing magic number ",
+              header.getMagic() == FileTxnLog.TXNLOG_MAGIC);
+    }
 }