Author: ggregory Date: Mon Jun 11 01:09:58 2012 New Revision: 1348698 URL: http://svn.apache.org/viewvc?rev=1348698&view=rev Log: [IO-269] Tailer locks file from deletion/rename on Windows.
Modified: commons/proper/io/trunk/src/changes/changes.xml commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java Modified: commons/proper/io/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/changes/changes.xml?rev=1348698&r1=1348697&r2=1348698&view=diff ============================================================================== --- commons/proper/io/trunk/src/changes/changes.xml (original) +++ commons/proper/io/trunk/src/changes/changes.xml Mon Jun 11 01:09:58 2012 @@ -47,6 +47,9 @@ The <action> type attribute can be add,u <body> <!-- The release date is the date RC is cut --> <release version="2.4" date="2012-TDB-TDB" description=""> + <action issue="IO-269" dev="ggregory" type="add" due-to="sebb"> + Tailer locks file from deletion/rename on Windows. + </action> <action issue="IO-279" dev="sebb" type="fix" due-to="Sergio Bossa, Chris Baron"> Tailer erroneously considers file as new. </action> Modified: commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java?rev=1348698&r1=1348697&r2=1348698&view=diff ============================================================================== --- commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java (original) +++ commons/proper/io/trunk/src/main/java/org/apache/commons/io/input/Tailer.java Mon Jun 11 01:09:58 2012 @@ -138,6 +138,11 @@ public class Tailer implements Runnable private final TailerListener listener; /** + * Whether to close and reopen the file whilst waiting for more input. + */ + private final boolean reOpen; + + /** * The tailer will run as long as this value is true. */ private volatile boolean run = true; @@ -173,6 +178,18 @@ public class Tailer implements Runnable } /** + * Creates a Tailer for the given file, with a delay other than the default 1.0s. + * @param file the file to follow. + * @param listener the TailerListener to use. + * @param delayMillis the delay between checks of the file for new content in milliseconds. + * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. + * @param reOpen if true, close and reopen the file between reading chunks + */ + public Tailer(File file, TailerListener listener, long delayMillis, boolean end, boolean reOpen) { + this(file, listener, delayMillis, end, reOpen, DEFAULT_BUFSIZE); + } + + /** * Creates a Tailer for the given file, with a specified buffer size. * @param file the file to follow. * @param listener the TailerListener to use. @@ -181,7 +198,19 @@ public class Tailer implements Runnable * @param bufSize Buffer size */ public Tailer(File file, TailerListener listener, long delayMillis, boolean end, int bufSize) { - + this(file, listener, delayMillis, end, false, bufSize); + } + + /** + * Creates a Tailer for the given file, with a specified buffer size. + * @param file the file to follow. + * @param listener the TailerListener to use. + * @param delayMillis the delay between checks of the file for new content in milliseconds. + * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. + * @param reOpen if true, close and reopen the file between reading chunks + * @param bufSize Buffer size + */ + public Tailer(File file, TailerListener listener, long delayMillis, boolean end, boolean reOpen, int bufSize) { this.file = file; this.delayMillis = delayMillis; this.end = end; @@ -191,6 +220,7 @@ public class Tailer implements Runnable // Save and prepare the listener this.listener = listener; listener.init(this); + this.reOpen = reOpen; } /** @@ -212,6 +242,26 @@ public class Tailer implements Runnable } /** + * Creates and starts a Tailer for the given file. + * + * @param file the file to follow. + * @param listener the TailerListener to use. + * @param delayMillis the delay between checks of the file for new content in milliseconds. + * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. + * @param reOpen whether to close/reopen the file between chunks + * @param bufSize buffer size. + * @return The new tailer + */ + public static Tailer create(File file, TailerListener listener, long delayMillis, boolean end, boolean reOpen, + int bufSize) { + Tailer tailer = new Tailer(file, listener, delayMillis, end, reOpen, bufSize); + Thread thread = new Thread(tailer); + thread.setDaemon(true); + thread.start(); + return tailer; + } + + /** * Creates and starts a Tailer for the given file with default buffer size. * * @param file the file to follow. @@ -225,6 +275,20 @@ public class Tailer implements Runnable } /** + * Creates and starts a Tailer for the given file with default buffer size. + * + * @param file the file to follow. + * @param listener the TailerListener to use. + * @param delayMillis the delay between checks of the file for new content in milliseconds. + * @param end Set to true to tail from the end of the file, false to tail from the beginning of the file. + * @param reOpen whether to close/reopen the file between chunks + * @return The new tailer + */ + public static Tailer create(File file, TailerListener listener, long delayMillis, boolean end, boolean reOpen) { + return create(file, listener, delayMillis, end, reOpen, DEFAULT_BUFSIZE); + } + + /** * Creates and starts a Tailer for the given file, starting at the beginning of the file * * @param file the file to follow. @@ -345,10 +409,17 @@ public class Tailer implements Runnable last = System.currentTimeMillis(); } } + if (reOpen) { + IOUtils.closeQuietly(reader); + } try { Thread.sleep(delayMillis); } catch (InterruptedException e) { } + if (run && reOpen) { + reader = new RandomAccessFile(file, RAF_MODE); + reader.seek(position); + } } } catch (Exception e) { Modified: commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java URL: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java?rev=1348698&r1=1348697&r2=1348698&view=diff ============================================================================== --- commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java (original) +++ commons/proper/io/trunk/src/test/java/org/apache/commons/io/input/TailerTest.java Mon Jun 11 01:09:58 2012 @@ -146,7 +146,9 @@ public class TailerTest extends FileBase final File file = new File(getTestDirectory(), "tailer1-test.txt"); createFile(file, 0); final TestTailerListener listener = new TestTailerListener(); - tailer = new Tailer(file, listener, delayMillis, false); + String osname = System.getProperty("os.name"); + boolean isWindows = osname.startsWith("Windows"); + tailer = new Tailer(file, listener, delayMillis, false, isWindows); final Thread thread = new Thread(tailer); thread.start(); @@ -178,9 +180,7 @@ public class TailerTest extends FileBase // Delete & re-create file.delete(); boolean exists = file.exists(); - String osname = System.getProperty("os.name"); - boolean isWindows = osname.startsWith("Windows"); - assertFalse("File should not exist (except on Windows)", exists && !isWindows); + assertFalse("File should not exist", exists); createFile(file, 0); Thread.sleep(testDelayMillis);