From 9fe0179a5fb04b7578c94684ecc5a6342ed79c06 Mon Sep 17 00:00:00 2001 From: Geoff Macartney Date: Fri, 4 Aug 2017 12:09:34 +0100 Subject: [PATCH 1/2] Sync file system on temp file before moving it. See https://issues.apache.org/jira/browse/BROOKLYN-526 --- .../persist/FileBasedStoreObjectAccessor.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/FileBasedStoreObjectAccessor.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/FileBasedStoreObjectAccessor.java index a8d7cf155a..6a3de10291 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/FileBasedStoreObjectAccessor.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/FileBasedStoreObjectAccessor.java @@ -19,8 +19,10 @@ package org.apache.brooklyn.core.mgmt.persist; import java.io.File; +import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; +import java.io.SyncFailedException; import java.util.Date; import org.apache.brooklyn.util.exceptions.Exceptions; @@ -87,7 +89,9 @@ public void put(String val) { public void put(ByteSource bytes) { try { FileUtil.setFilePermissionsTo600(tmpFile); - Streams.copyClose(bytes.openStream(), new FileOutputStream(tmpFile)); + final FileOutputStream tempStream = new FileOutputStream(tmpFile); + Streams.copyClose(bytes.openStream(), tempStream); + syncFileSystem(tempStream.getFD()); FileBasedObjectStore.moveFile(tmpFile, file); } catch (IOException e) { throw Exceptions.propagateAnnotated("Problem writing data to file "+file+" (via temporary file "+tmpFile+")", e); @@ -96,6 +100,25 @@ public void put(ByteSource bytes) { } } + private void syncFileSystem(final FileDescriptor fd) throws SyncFailedException { + // Simple retry a number of times; avoids Repeater to avoid complications of timeouts and separate threads + int maxTries = 3; + + SyncFailedException sfe = null; + for (int c = 0 ; c < maxTries ; c++) { + try { + fd.sync(); + sfe = null; + break; + } catch (SyncFailedException e) { + sfe = e; + } + } + if (sfe != null) { + throw sfe; + } + } + // TODO Should this write to the temporary file? Otherwise we'll risk getting a partial view of the write. @Override public void append(String val) { From c5cbc0843d9635072d09379ed053968a2e670387 Mon Sep 17 00:00:00 2001 From: Geoff Macartney Date: Fri, 8 Sep 2017 10:21:25 +0100 Subject: [PATCH 2/2] Sync before close --- .../mgmt/persist/FileBasedStoreObjectAccessor.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/FileBasedStoreObjectAccessor.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/FileBasedStoreObjectAccessor.java index 6a3de10291..9387fe3f07 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/FileBasedStoreObjectAccessor.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/FileBasedStoreObjectAccessor.java @@ -22,6 +22,7 @@ import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.SyncFailedException; import java.util.Date; @@ -90,8 +91,15 @@ public void put(ByteSource bytes) { try { FileUtil.setFilePermissionsTo600(tmpFile); final FileOutputStream tempStream = new FileOutputStream(tmpFile); - Streams.copyClose(bytes.openStream(), tempStream); - syncFileSystem(tempStream.getFD()); + final InputStream byteStream = bytes.openStream(); + try { + Streams.copy(byteStream, tempStream); + syncFileSystem(tempStream.getFD()); + } finally { + Streams.closeQuietly(byteStream); + Streams.closeQuietly(tempStream); + } + FileBasedObjectStore.moveFile(tmpFile, file); } catch (IOException e) { throw Exceptions.propagateAnnotated("Problem writing data to file "+file+" (via temporary file "+tmpFile+")", e);