Created
March 26, 2013 20:18
-
-
Save krummas/5248821 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 891c3126dc9e62c09cfcd7204f68f3c9e848102e Mon Sep 17 00:00:00 2001 | |
From: Marcus Eriksson <[email protected]> | |
Date: Tue, 26 Mar 2013 21:14:33 +0100 | |
Subject: [PATCH] use Java7 apis for moving files and creating symlinks | |
--- | |
.../cassandra/db/compaction/LeveledManifest.java | 2 +- | |
.../org/apache/cassandra/io/util/FileUtils.java | 58 ++++++++++++++++- | |
src/java/org/apache/cassandra/utils/CLibrary.java | 67 -------------------- | |
test/unit/org/apache/cassandra/db/ScrubTest.java | 2 +- | |
.../cassandra/io/sstable/SSTableReaderTest.java | 2 +- | |
5 files changed, 57 insertions(+), 74 deletions(-) | |
diff --git a/src/java/org/apache/cassandra/db/compaction/LeveledManifest.java b/src/java/org/apache/cassandra/db/compaction/LeveledManifest.java | |
index 71356f0..83d3a70 100644 | |
--- a/src/java/org/apache/cassandra/db/compaction/LeveledManifest.java | |
+++ b/src/java/org/apache/cassandra/db/compaction/LeveledManifest.java | |
@@ -572,6 +572,6 @@ public class LeveledManifest | |
SSTableMetadata.serializer.legacySerialize(metadata, descriptor, dos); | |
dos.flush(); | |
dos.close(); | |
- FileUtils.renameWithConfirm(filename + "-tmp", filename); | |
+ FileUtils.replaceWithOutConfirm(filename + "-tmp", filename); | |
} | |
} | |
diff --git a/src/java/org/apache/cassandra/io/util/FileUtils.java b/src/java/org/apache/cassandra/io/util/FileUtils.java | |
index 69038fa..2b2ae03 100644 | |
--- a/src/java/org/apache/cassandra/io/util/FileUtils.java | |
+++ b/src/java/org/apache/cassandra/io/util/FileUtils.java | |
@@ -21,6 +21,10 @@ import java.io.*; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.nio.MappedByteBuffer; | |
+import java.nio.file.AtomicMoveNotSupportedException; | |
+import java.nio.file.Files; | |
+import java.nio.file.Path; | |
+import java.nio.file.StandardCopyOption; | |
import java.text.DecimalFormat; | |
import java.util.Arrays; | |
@@ -34,7 +38,6 @@ import org.apache.cassandra.io.FSError; | |
import org.apache.cassandra.io.FSReadError; | |
import org.apache.cassandra.io.FSWriteError; | |
import org.apache.cassandra.service.StorageService; | |
-import org.apache.cassandra.utils.CLibrary; | |
public class FileUtils | |
{ | |
@@ -73,7 +76,7 @@ public class FileUtils | |
try | |
{ | |
- CLibrary.createHardLink(from, to); | |
+ Files.createLink(to.toPath(), from.toPath()); | |
} | |
catch (IOException e) | |
{ | |
@@ -114,7 +117,46 @@ public class FileUtils | |
public static void renameWithOutConfirm(String from, String to) | |
{ | |
- new File(from).renameTo(new File(to)); | |
+ Path fromPath = new File(from).toPath(); | |
+ Path toPath = new File(to).toPath(); | |
+ try | |
+ { | |
+ try | |
+ { | |
+ Files.move(fromPath, toPath, StandardCopyOption.ATOMIC_MOVE); | |
+ } | |
+ catch (AtomicMoveNotSupportedException e) | |
+ { | |
+ Files.move(fromPath, toPath); | |
+ } | |
+ } | |
+ catch (IOException e) | |
+ { | |
+ if (logger.isTraceEnabled()) | |
+ logger.trace("Could not move file "+from+" to "+to, e); | |
+ } | |
+ } | |
+ | |
+ public static void replaceWithOutConfirm(String from, String to) | |
+ { | |
+ Path fromPath = new File(from).toPath(); | |
+ Path toPath = new File(to).toPath(); | |
+ try | |
+ { | |
+ try | |
+ { | |
+ Files.move(fromPath, toPath, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); | |
+ } | |
+ catch (AtomicMoveNotSupportedException e) | |
+ { | |
+ logger.debug("Atomic replace not supported", e); | |
+ Files.move(fromPath, toPath, StandardCopyOption.REPLACE_EXISTING); | |
+ } | |
+ } | |
+ catch (IOException e) | |
+ { | |
+ logger.error("Could not replace file "+to+" with "+from, e); | |
+ } | |
} | |
public static void renameWithConfirm(String from, String to) | |
@@ -125,12 +167,20 @@ public class FileUtils | |
public static void renameWithConfirm(File from, File to) | |
{ | |
assert from.exists(); | |
+ Path fromPath = from.toPath(); | |
+ Path toPath = to.toPath(); | |
if (logger.isDebugEnabled()) | |
logger.debug((String.format("Renaming %s to %s", from.getPath(), to.getPath()))); | |
// this is not FSWE because usually when we see it it's because we didn't close the file before renaming it, | |
// and Windows is picky about that. | |
- if (!from.renameTo(to)) | |
+ try | |
+ { | |
+ Files.move(fromPath, toPath); | |
+ } | |
+ catch (IOException e) | |
+ { | |
throw new RuntimeException(String.format("Failed to rename %s to %s", from.getPath(), to.getPath())); | |
+ } | |
} | |
public static void truncate(String path, long size) | |
diff --git a/src/java/org/apache/cassandra/utils/CLibrary.java b/src/java/org/apache/cassandra/utils/CLibrary.java | |
index 2f6e088..b57c8bf 100644 | |
--- a/src/java/org/apache/cassandra/utils/CLibrary.java | |
+++ b/src/java/org/apache/cassandra/utils/CLibrary.java | |
@@ -74,8 +74,6 @@ public final class CLibrary | |
private static native int mlockall(int flags) throws LastErrorException; | |
private static native int munlockall() throws LastErrorException; | |
- private static native int link(String from, String to) throws LastErrorException; | |
- | |
// fcntl - manipulate file descriptor, `man 2 fcntl` | |
public static native int fcntl(int fd, int command, long flags) throws LastErrorException; | |
@@ -131,71 +129,6 @@ public final class CLibrary | |
} | |
} | |
- /** | |
- * Create a hard link for a given file. | |
- * | |
- * @param sourceFile The name of the source file. | |
- * @param destinationFile The name of the destination file. | |
- * | |
- * @throws java.io.IOException if an error has occurred while creating the link. | |
- */ | |
- public static void createHardLink(File sourceFile, File destinationFile) throws IOException | |
- { | |
- try | |
- { | |
- link(sourceFile.getAbsolutePath(), destinationFile.getAbsolutePath()); | |
- } | |
- catch (UnsatisfiedLinkError e) | |
- { | |
- createHardLinkWithExec(sourceFile, destinationFile); | |
- } | |
- catch (RuntimeException e) | |
- { | |
- logger.error("Unable to create hard link", e); | |
- if (!(e instanceof LastErrorException)) | |
- throw e; | |
- // there are 17 different error codes listed on the man page. punt until/unless we find which | |
- // ones actually turn up in practice. | |
- throw new IOException(String.format("Unable to create hard link from %s to %s (errno %d)", | |
- sourceFile, destinationFile, errno(e))); | |
- } | |
- } | |
- | |
- public static void createHardLinkWithExec(File sourceFile, File destinationFile) throws IOException | |
- { | |
- String osname = System.getProperty("os.name"); | |
- ProcessBuilder pb; | |
- if (osname.startsWith("Windows")) | |
- { | |
- float osversion = Float.parseFloat(System.getProperty("os.version")); | |
- if (osversion >= 6.0f) | |
- { | |
- pb = new ProcessBuilder("cmd", "/c", "mklink", "/H", destinationFile.getAbsolutePath(), sourceFile.getAbsolutePath()); | |
- } | |
- else | |
- { | |
- pb = new ProcessBuilder("fsutil", "hardlink", "create", destinationFile.getAbsolutePath(), sourceFile.getAbsolutePath()); | |
- } | |
- } | |
- else | |
- { | |
- pb = new ProcessBuilder("ln", sourceFile.getAbsolutePath(), destinationFile.getAbsolutePath()); | |
- pb.redirectErrorStream(true); | |
- } | |
- try | |
- { | |
- FBUtilities.exec(pb); | |
- } | |
- catch (IOException ex) | |
- { | |
- String st = osname.startsWith("Windows") | |
- ? "Unable to create hard link. This probably means your data directory path is too long. Exception follows:" | |
- : "Unable to create hard link with exec. Suggest installing JNA to avoid the need to exec entirely. Exception follows: "; | |
- logger.error(st, ex); | |
- throw ex; | |
- } | |
- } | |
- | |
public static void trySkipCache(int fd, long offset, int len) | |
{ | |
if (fd < 0) | |
diff --git a/test/unit/org/apache/cassandra/db/ScrubTest.java b/test/unit/org/apache/cassandra/db/ScrubTest.java | |
index e800bbb..16a263b 100644 | |
--- a/test/unit/org/apache/cassandra/db/ScrubTest.java | |
+++ b/test/unit/org/apache/cassandra/db/ScrubTest.java | |
@@ -72,7 +72,7 @@ public class ScrubTest extends SchemaLoader | |
if (!srcFile.getName().contains(cf)) | |
continue; | |
File destFile = new File(destDir, srcFile.getName()); | |
- CLibrary.createHardLink(srcFile, destFile); | |
+ FileUtils.createHardLink(srcFile, destFile); | |
assert destFile.exists() : destFile.getAbsoluteFile(); | |
diff --git a/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java b/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java | |
index a8b6d64..7f4bad2 100644 | |
--- a/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java | |
+++ b/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java | |
@@ -238,7 +238,7 @@ public class SSTableReaderTest extends SchemaLoader | |
if (!srcFile.getName().startsWith("Indexed1")) | |
continue; | |
File destFile = new File(destDir, srcFile.getName()); | |
- CLibrary.createHardLink(srcFile, destFile); | |
+ FileUtils.createHardLink(srcFile, destFile); | |
assert destFile.exists() : destFile.getAbsoluteFile(); | |
} | |
-- | |
1.7.2.5 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment