Author: davsclaus Date: Wed Mar 27 11:05:32 2013 New Revision: 1461514 URL: http://svn.apache.org/r1461514 Log: CAMEL-6205: Added forceWrites option to file producer. Thanks to Christian Tytgat for the patch.
Added: camel/branches/camel-2.10.x/camel-core/src/test/java/org/apache/camel/component/file/FileProducerNoForcedWritesTest.java - copied unchanged from r1461507, camel/trunk/camel-core/src/test/java/org/apache/camel/component/file/FileProducerNoForcedWritesTest.java Modified: camel/branches/camel-2.10.x/ (props changed) camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IOHelper.java Propchange: camel/branches/camel-2.10.x/ ------------------------------------------------------------------------------ Merged /camel/trunk:r1461507 Propchange: camel/branches/camel-2.10.x/ ------------------------------------------------------------------------------ Binary property 'svnmerge-integrated' - no diff available. Modified: camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java?rev=1461514&r1=1461513&r2=1461514&view=diff ============================================================================== --- camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java (original) +++ camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileEndpoint.java Wed Mar 27 11:05:32 2013 @@ -34,6 +34,7 @@ public class FileEndpoint extends Generi private FileOperations operations = new FileOperations(this); private File file; private boolean copyAndDeleteOnRenameFail = true; + private boolean forceWrites = true; public FileEndpoint() { // use marker file as default exclusive read locks @@ -165,4 +166,12 @@ public class FileEndpoint extends Generi public void setCopyAndDeleteOnRenameFail(boolean copyAndDeleteOnRenameFail) { this.copyAndDeleteOnRenameFail = copyAndDeleteOnRenameFail; } + + public boolean isForceWrites() { + return forceWrites; + } + + public void setForceWrites(boolean forceWrites) { + this.forceWrites = forceWrites; + } } Modified: camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java?rev=1461514&r1=1461513&r2=1461514&view=diff ============================================================================== --- camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java (original) +++ camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/component/file/FileOperations.java Wed Mar 27 11:05:32 2013 @@ -354,9 +354,7 @@ public class FileOperations implements G } } finally { IOHelper.close(in, source.getName(), LOG); - // force updates to be written, and then close afterwards - IOHelper.force(out, target.getName(), LOG); - IOHelper.close(out, target.getName(), LOG); + IOHelper.close(out, target.getName(), LOG, endpoint.isForceWrites()); } } @@ -378,25 +376,24 @@ public class FileOperations implements G } } finally { IOHelper.close(in, target.getName(), LOG); - // force updates to be written, and then close afterwards - IOHelper.force(out, target.getName(), LOG); - IOHelper.close(out, target.getName(), LOG); + IOHelper.close(out, target.getName(), LOG, endpoint.isForceWrites()); } } private void writeFileByReaderWithCharset(Reader in, File target, String charset) throws IOException { boolean append = endpoint.getFileExist() == GenericFileExist.Append; - Writer out = IOConverter.toWriter(target, append, charset); + FileOutputStream os = new FileOutputStream(target, append); + Writer out = IOConverter.toWriter(os, charset); try { LOG.debug("Using Reader to write file: {} with charset: {}", target, charset); int size = endpoint.getBufferSize(); IOHelper.copy(in, out, size); } finally { IOHelper.close(in, target.getName(), LOG); - IOHelper.close(out, target.getName(), LOG); + IOHelper.close(out, os, target.getName(), LOG, endpoint.isForceWrites()); } } - + /** * Creates a new file if the file doesn't exist. * If the endpoint's existing file logic is set to 'Override' then the target file will be truncated @@ -411,8 +408,7 @@ public class FileOperations implements G try { out.truncate(0); } finally { - IOHelper.force(out, target.getName(), LOG); - IOHelper.close(out, target.getName(), LOG); + IOHelper.close(out, target.getName(), LOG, endpoint.isForceWrites()); } } } Modified: camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java?rev=1461514&r1=1461513&r2=1461514&view=diff ============================================================================== --- camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java (original) +++ camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/converter/IOConverter.java Wed Mar 27 11:05:32 2013 @@ -130,16 +130,21 @@ public final class IOConverter { */ @Deprecated public static BufferedWriter toWriter(File file) throws IOException { - return toWriter(file, false, IOHelper.getCharsetName(null, true)); + FileOutputStream os = new FileOutputStream(file, false); + return toWriter(os, IOHelper.getCharsetName(null, true)); } @Converter public static BufferedWriter toWriter(File file, Exchange exchange) throws IOException { - return toWriter(file, false, IOHelper.getCharsetName(exchange)); + FileOutputStream os = new FileOutputStream(file, false); + return toWriter(os, IOHelper.getCharsetName(exchange)); } public static BufferedWriter toWriter(File file, boolean append, String charset) throws IOException { - FileOutputStream os = new FileOutputStream(file, append); + return toWriter(new FileOutputStream(file, append), charset); + } + + public static BufferedWriter toWriter(FileOutputStream os, String charset) throws IOException { return IOHelper.buffered(new EncodingFileWriter(os, charset)); } Modified: camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IOHelper.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IOHelper.java?rev=1461514&r1=1461513&r2=1461514&view=diff ============================================================================== --- camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IOHelper.java (original) +++ camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IOHelper.java Wed Mar 27 11:05:32 2013 @@ -21,6 +21,7 @@ import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.Closeable; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -230,6 +231,62 @@ public final class IOHelper { } /** + * Forces any updates to a FileOutputStream be written to the storage device that contains it. + * + * @param os the file output stream + * @param name the name of the resource + * @param log the log to use when reporting warnings, will use this class's own {@link Logger} if <tt>log == null</tt> + */ + public static void force(FileOutputStream os, String name, Logger log) { + try { + if (os != null) { + os.getFD().sync(); + } + } catch (Exception e) { + if (log == null) { + // then fallback to use the own Logger + log = LOG; + } + if (name != null) { + log.warn("Cannot sync FileDescriptor: " + name + ". Reason: " + e.getMessage(), e); + } else { + log.warn("Cannot sync FileDescriptor. Reason: " + e.getMessage(), e); + } + } + } + + /** + * Closes the given writer, logging any closing exceptions to the given log. + * An associated FileOutputStream can optionally be forced to disk. + * + * @param writer the writer to close + * @param os an underlying FileOutputStream that will to be forced to disk according to the the force parameter + * @param name the name of the resource + * @param log the log to use when reporting warnings, will use this class's own {@link Logger} if <tt>log == null</tt> + * @param force forces the FileOutputStream to disk + */ + public static void close(Writer writer, FileOutputStream os, String name, Logger log, boolean force) { + if (writer != null && force) { + // flush the writer prior to syncing the FD + try { + writer.flush(); + } catch (Exception e) { + if (log == null) { + // then fallback to use the own Logger + log = LOG; + } + if (name != null) { + log.warn("Cannot flush Writer: " + name + ". Reason: " + e.getMessage(), e); + } else { + log.warn("Cannot flush Writer. Reason: " + e.getMessage(), e); + } + } + force(os, name, log); + } + close(writer, name, log); + } + + /** * Closes the given resource if it is available, logging any closing exceptions to the given log. * * @param closeable the object to close @@ -255,6 +312,22 @@ public final class IOHelper { } /** + * Closes the given channel if it is available, logging any closing exceptions to the given log. + * The file's channel can optionally be forced to disk. + * + * @param channel the file channel + * @param name the name of the resource + * @param log the log to use when reporting warnings, will use this class's own {@link Logger} if <tt>log == null</tt> + * @param force forces the file channel to disk + */ + public static void close(FileChannel channel, String name, Logger log, boolean force) { + if (force) { + force(channel, name, log); + } + close(channel, name, log); + } + + /** * Closes the given resource if it is available. * * @param closeable the object to close