Skip to content

Instantly share code, notes, and snippets.

@krummas
Created March 26, 2013 20:18
Show Gist options
  • Save krummas/5248821 to your computer and use it in GitHub Desktop.
Save krummas/5248821 to your computer and use it in GitHub Desktop.
From 891c3126dc9e62c09cfcd7204f68f3c9e848102e Mon Sep 17 00:00:00 2001
From: Marcus Eriksson <marcuse@spotify.com>
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