diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileSnap.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileSnap.java index 26fc402a7e8..9cc7118ee3d 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileSnap.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/FileSnap.java @@ -231,7 +231,7 @@ public synchronized void serialize( File snapShot, boolean fsync) throws IOException { if (!close) { - try (CheckedOutputStream snapOS = SnapStream.getOutputStream(snapShot)) { + try (CheckedOutputStream snapOS = SnapStream.getOutputStream(snapShot, fsync)) { OutputArchive oa = BinaryOutputArchive.getArchive(snapOS); FileHeader header = new FileHeader(SNAP_MAGIC, VERSION, dbId); serialize(dt, sessions, oa, header); diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/SnapStream.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/SnapStream.java index 222709686dc..b812aa1f9ef 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/SnapStream.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/persistence/SnapStream.java @@ -37,6 +37,7 @@ import java.util.zip.GZIPOutputStream; import org.apache.jute.InputArchive; import org.apache.jute.OutputArchive; +import org.apache.zookeeper.common.AtomicFileOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xerial.snappy.SnappyCodec; @@ -119,11 +120,12 @@ public static CheckedInputStream getInputStream(File file) throws IOException { * Return the OutputStream based on predefined stream mode. * * @param file the file the OutputStream writes to + * @param fsync sync the file immediately after write * @return the specific OutputStream * @throws IOException */ - public static CheckedOutputStream getOutputStream(File file) throws IOException { - FileOutputStream fos = new FileOutputStream(file); + public static CheckedOutputStream getOutputStream(File file, boolean fsync) throws IOException { + OutputStream fos = fsync ? new AtomicFileOutputStream(file) : new FileOutputStream(file); OutputStream os; switch (streamMode) { case GZIP: diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/SnapStreamTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/SnapStreamTest.java index d884d1e0675..65457803679 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/SnapStreamTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/persistence/SnapStreamTest.java @@ -79,12 +79,17 @@ public void testSerializeDeserializeWithGZIP() throws IOException { } private void testSerializeDeserialize(StreamMode mode, String fileSuffix) throws IOException { + testSerializeDeserialize(mode, fileSuffix, false); + testSerializeDeserialize(mode, fileSuffix, true); + } + + private void testSerializeDeserialize(StreamMode mode, String fileSuffix, boolean fsync) throws IOException { SnapStream.setStreamMode(mode); // serialize with gzip stream File tmpDir = createTmpDir(); File file = new File(tmpDir, "snapshot.180000e3a2" + fileSuffix); - CheckedOutputStream os = SnapStream.getOutputStream(file); + CheckedOutputStream os = SnapStream.getOutputStream(file, fsync); OutputArchive oa = BinaryOutputArchive.getArchive(os); FileHeader header = new FileHeader(FileSnap.SNAP_MAGIC, 2, 1); header.serialize(oa, "fileheader"); @@ -103,20 +108,25 @@ private void testSerializeDeserialize(StreamMode mode, String fileSuffix) throws SnapStream.checkSealIntegrity(is, ia); } - private void checkInvalidSnapshot(String filename) throws IOException { + private void checkInvalidSnapshot(String filename, boolean fsync) throws IOException { // set the output stream mode to CHECKED SnapStream.setStreamMode(StreamMode.CHECKED); // serialize to CHECKED file without magic header File tmpDir = createTmpDir(); File file = new File(tmpDir, filename); - OutputStream os = SnapStream.getOutputStream(file); + OutputStream os = SnapStream.getOutputStream(file, fsync); os.write(1); os.flush(); os.close(); assertFalse(SnapStream.isValidSnapshot(file)); } + private void checkInvalidSnapshot(String filename) throws IOException { + checkInvalidSnapshot(filename, false); + checkInvalidSnapshot(filename, true); + } + @Test public void testInvalidSnapshot() throws IOException { assertFalse(SnapStream.isValidSnapshot(null));