Skip to content

Commit

Permalink
[JENKINS-34855] Make atomic file write more atomic by using JDK 7 apis.
Browse files Browse the repository at this point in the history
  • Loading branch information
christ66 committed Sep 17, 2016
1 parent 08def67 commit 0a7b656
Showing 1 changed file with 32 additions and 13 deletions.
45 changes: 32 additions & 13 deletions core/src/main/java/hudson/util/AtomicFileWriter.java
Expand Up @@ -32,6 +32,12 @@
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;

/**
* Buffered {@link FileWriter} that supports atomic operations.
Expand All @@ -45,8 +51,8 @@
public class AtomicFileWriter extends Writer {

private final Writer core;
private final File tmpFile;
private final File destFile;
private final Path tmpFile;
private final Path destFile;

/**
* Writes with UTF-8 encoding.
Expand All @@ -60,17 +66,17 @@ public AtomicFileWriter(File f) throws IOException {
* File encoding to write. If null, platform default encoding is chosen.
*/
public AtomicFileWriter(File f, String encoding) throws IOException {
File dir = f.getParentFile();
Path dir = f.toPath().getParent();
try {
dir.mkdirs();
tmpFile = File.createTempFile("atomic",null, dir);
Files.createDirectories(dir);
tmpFile = Files.createTempFile(dir, "atomic", null, (FileAttribute<?>) null);
} catch (IOException e) {
throw new IOException("Failed to create a temporary file in "+ dir,e);
}
destFile = f;
destFile = f.toPath();
if (encoding==null)
encoding = Charset.defaultCharset().name();
core = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tmpFile),encoding));
core = Files.newBufferedWriter(tmpFile, Charset.forName(encoding), StandardOpenOption.SYNC);
}

@Override
Expand Down Expand Up @@ -103,34 +109,47 @@ public void close() throws IOException {
*/
public void abort() throws IOException {
close();
tmpFile.delete();
Files.deleteIfExists(tmpFile);
}

public void commit() throws IOException {
close();
if (destFile.exists()) {
if (Files.exists(destFile)) {
try {
Util.deleteFile(destFile);
Files.delete(tmpFile); // First try with NIO.
Util.deleteFile(destFile.toFile()); // Then try with the util method.
} catch (IOException x) {
tmpFile.delete();
Files.delete(tmpFile);
throw x;
}
}
tmpFile.renameTo(destFile);
Files.move(tmpFile, destFile, null);
}

@Override
protected void finalize() throws Throwable {
// one way or the other, temporary file should be deleted.
close();
tmpFile.delete();
Files.deleteIfExists(tmpFile);
}

/**
* Until the data is committed, this file captures
* the written content.
*
* @deprecated Use getTemporaryPath() for JDK 7+
*/
@Deprecated
public File getTemporaryFile() {
return tmpFile.toFile();
}

/**
* Until the data is committed, this file captures
* the written content.
*
*/
public Path getTemporaryPath() {
return tmpFile;
}
}

0 comments on commit 0a7b656

Please sign in to comment.