下面列出了怎么用java.nio.file.AtomicMoveNotSupportedException的API类实例代码及写法,或者点击链接到github查看源代码。
void create() throws IOException {
if (file.exists()) {
throw new IllegalStateException("Failed to create a PID file. A file already exists: " +
file.getPath());
}
final int pid = SystemInfo.pid();
final Path temp = Files.createTempFile("central-dogma", ".tmp");
Files.write(temp, Integer.toString(pid).getBytes());
try {
Files.move(temp, file.toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (AtomicMoveNotSupportedException e) {
Files.move(temp, file.toPath());
}
logger.debug("A PID file has been created: {}", file);
}
public Path atomicFileMoveOrReplace(Path sourceFile, Path targetFile) throws IOException
{
try
{
return Files.move(sourceFile, targetFile, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
}
catch(AtomicMoveNotSupportedException e)
{
if (sourceFile.toFile().renameTo(targetFile.toFile()))
{
return targetFile;
}
else
{
throw new RuntimeException("Atomic move is unsupported and rename from : '"
+ sourceFile + "' to: '" + targetFile + "' failed.");
}
}
}
@Override
public void move(Path source, Path target, CopyOption... options) throws IOException {
HashSet<CopyOption> copyOptions = Sets.newHashSet(options);
if (copyOptions.contains(StandardCopyOption.ATOMIC_MOVE)) {
throw new AtomicMoveNotSupportedException(source.toString(), target.toString(),
"ATOMIC_MOVE not supported yet");
}
if (Files.isDirectory(source)) {
MCRPath src = MCRFileSystemUtils.checkPathAbsolute(source);
MCRDirectory srcRootDirectory = MCRFileSystemUtils.getFileCollection(src.getOwner());
if (srcRootDirectory.hasChildren()) {
throw new IOException("Directory is not empty");
}
}
copy(source, target, options);
delete(source);
}
@Override
public void move(Path source, Path target, CopyOption... options) throws IOException {
HashSet<CopyOption> copyOptions = Sets.newHashSet(options);
if (copyOptions.contains(StandardCopyOption.ATOMIC_MOVE)) {
throw new AtomicMoveNotSupportedException(source.toString(), target.toString(),
"ATOMIC_MOVE not supported yet");
}
if (Files.isDirectory(source)) {
MCRPath src = MCRFileSystemUtils.checkPathAbsolute(source);
MCRDirectory srcRootDirectory = getRootDirectory(src);
if (srcRootDirectory.hasChildren()) {
throw new IOException("Directory is not empty");
}
}
copy(source, target, options);
delete(source);
}
public void testRenameTmpFile() throws IOException {
try (Directory directory = getDirectory(createTempDir())) {
final String name;
try (IndexOutput out = directory.createTempOutput("foo.cfs", "", IOContext.DEFAULT)) {
out.writeInt(1);
name = out.getName();
}
assertEquals(1, Arrays.stream(directory.listAll()).filter(f -> f.equals(name)).count());
assertEquals(0, Arrays.stream(directory.listAll()).filter(f -> f.equals("foo.cfs")).count());
directory.rename(name, "foo.cfs");
assertEquals(1, Arrays.stream(directory.listAll()).filter(f -> f.equals("foo.cfs")).count());
assertEquals(0, Arrays.stream(directory.listAll()).filter(f -> f.equals(name)).count());
}
try (Directory directory= newFSSwitchDirectory(Collections.singleton("bar"))) {
String brokenName;
try (IndexOutput out = directory.createTempOutput("foo", "bar", IOContext.DEFAULT)) {
out.writeInt(1);
brokenName = out.getName();
}
AtomicMoveNotSupportedException exception = expectThrows(AtomicMoveNotSupportedException.class,
() -> directory.rename(brokenName, "foo.bar"));
assertEquals("foo_bar_0.tmp -> foo.bar: source and dest are in different directories", exception.getMessage());
}
}
/**
* Override for more efficient moves.
*
* Intended for use with replication - use
* carefully - some Directory wrappers will
* cache files for example.
*
* You should first {@link Directory#sync(java.util.Collection)} any file that will be
* moved or avoid cached files through settings.
*
* @throws IOException
* If there is a low-level I/O error.
*/
@Override
public void move(Directory fromDir, Directory toDir, String fileName, IOContext ioContext)
throws IOException {
Directory baseFromDir = getBaseDir(fromDir);
Directory baseToDir = getBaseDir(toDir);
if (baseFromDir instanceof FSDirectory && baseToDir instanceof FSDirectory) {
Path path1 = ((FSDirectory) baseFromDir).getDirectory().toAbsolutePath();
Path path2 = ((FSDirectory) baseToDir).getDirectory().toAbsolutePath();
try {
Files.move(path1.resolve(fileName), path2.resolve(fileName), StandardCopyOption.ATOMIC_MOVE);
} catch (AtomicMoveNotSupportedException e) {
Files.move(path1.resolve(fileName), path2.resolve(fileName));
}
return;
}
super.move(fromDir, toDir, fileName, ioContext);
}
public void renameWithOverwrite(Directory dir, String fileName, String toName) throws IOException {
Directory baseDir = getBaseDir(dir);
if (baseDir instanceof FSDirectory) {
Path path = ((FSDirectory) baseDir).getDirectory().toAbsolutePath();
try {
Files.move(path.resolve(fileName),
path.resolve(toName), StandardCopyOption.ATOMIC_MOVE,
StandardCopyOption.REPLACE_EXISTING);
} catch (AtomicMoveNotSupportedException e) {
Files.move(FileSystems.getDefault().getPath(path.toString(), fileName),
FileSystems.getDefault().getPath(path.toString(), toName), StandardCopyOption.REPLACE_EXISTING);
}
} else {
super.renameWithOverwrite(dir, fileName, toName);
}
}
private void saveToFile(final File propertiesFile) throws IOException
{
File parent = propertiesFile.getParentFile();
parent.mkdirs();
File tempFile = new File(parent, RuneLite.DEFAULT_CONFIG_FILE.getName() + ".tmp");
try (FileOutputStream out = new FileOutputStream(tempFile))
{
out.getChannel().lock();
properties.store(new OutputStreamWriter(out, StandardCharsets.UTF_8), "RuneLite configuration");
// FileOutputStream.close() closes the associated channel, which frees the lock
}
try
{
Files.move(tempFile.toPath(), propertiesFile.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
}
catch (AtomicMoveNotSupportedException ex)
{
log.debug("atomic move not supported", ex);
Files.move(tempFile.toPath(), propertiesFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
@Override
public void copyIfLocked(final Path source, final Path target, final Mover mover) throws IOException {
checkNotNull(source);
checkNotNull(target);
try {
mover.accept(source, target);
}
catch (AtomicMoveNotSupportedException atomicMoveNotSupported) {
throw atomicMoveNotSupported;
}
catch (FileSystemException e) { // NOSONAR
// Windows can throw a FileSystemException on move or moveAtomic
// if the file is in use; in this case, copy and attempt to delete
// source
log.warn("Using copy to move {} to {}", source, target);
copy(source, target);
try {
delete(source);
}
catch (IOException deleteException) { // NOSONAR
log.error("Unable to delete {} after move: {}", source, deleteException.getMessage());
}
}
}
@Test
public void temporaryBlobMoveFallback() throws Exception {
final byte[] content = new byte[TEST_DATA_LENGTH];
new Random().nextBytes(content);
doThrow(new AtomicMoveNotSupportedException("", "", "")).when(fileOperations).moveAtomic(any(), any());
final Blob blob = underTest.create(new ByteArrayInputStream(content), TEST_HEADERS);
verifyMoveOperations(blob);
final byte[] output = extractContent(blob);
assertThat("data must survive", content, is(equalTo(output)));
final BlobMetrics metrics = blob.getMetrics();
assertThat("size must be calculated correctly", metrics.getContentSize(), is(equalTo((long) TEST_DATA_LENGTH)));
}
@Override
public void close() throws IOException {
try {
this.channel.position(0); // reset channel to beginning to compute full SHA1
String calculatedSha1 = ZsyncUtil.computeSha1(this.channel);
if (!this.sha1.equals(calculatedSha1)) {
throw new ChecksumValidationIOException(this.sha1, calculatedSha1);
}
try {
Files.move(this.tempPath, this.path, REPLACE_EXISTING, ATOMIC_MOVE);
} catch (AtomicMoveNotSupportedException e) {
Files.move(this.tempPath, this.path, REPLACE_EXISTING);
}
Files.setLastModifiedTime(this.path, fromMillis(this.mtime));
} finally {
this.channel.close();
this.listener.close();
}
}
/**
* Attempts an fs level atomic move then fall back to pure java rename.
* Assumes files are on same mount point.
* Overwriting existing destFile
*/
static void moveFile(File srcFile, File destFile) throws IOException, InterruptedException {
if (destFile.isDirectory()) {
deleteCompletely(destFile);
}
try {
Files.move(srcFile.toPath(), destFile.toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (AtomicMoveNotSupportedException e) {
if (!WARNED_ON_NON_ATOMIC_FILE_UPDATES) {
WARNED_ON_NON_ATOMIC_FILE_UPDATES = true;
log.warn("Unable to perform atomic file update ("+srcFile+" to "+destFile+"); file system not recommended for production HA/DR");
}
Files.move(srcFile.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
if (log.isTraceEnabled()) {
log.trace("Completly moved from {} to {} completed", new Object[] { srcFile, destFile });
}
}
/**
* Writes list of strings to file.
*
* @param lines list of strings to write
* @param to Path of file where lines should be written
* @throws IOException if error occurred during writing
* @throws IllegalArgumentException if <pre>lines</pre> is empty list
*/
public static void saveConfig(List<String> lines, Path to) throws IOException {
if (lines.isEmpty()) {
throw new IllegalArgumentException("lines cannot be empty");
}
Path temp = to.toAbsolutePath().getParent().resolve(to.getFileName().toString() + "__tmp");
Files.write(temp, lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE);
try {
Files.move(temp, to, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
} catch (AtomicMoveNotSupportedException e) {
Files.move(temp, to, StandardCopyOption.REPLACE_EXISTING);
}
}
@Override
public void move(Path srcpath, SecureDirectoryStream<Path> targetdir, Path targetpath) throws IOException {
checkClosed();
checkFileSystem(srcpath);
checkFileSystem(targetpath);
throw new AtomicMoveNotSupportedException(srcpath.toString(), targetpath.toString(),
"Currently not implemented");
}
@Override
public void rename(String source, String dest) throws IOException {
Directory sourceDir = getDirectory(source);
// won't happen with standard lucene index files since pending and commit will
// always have the same extension ("")
if (sourceDir != getDirectory(dest)) {
throw new AtomicMoveNotSupportedException(source, dest, "source and dest are in different directories");
}
sourceDir.rename(source, dest);
}
@Override
public void moveAtomic(final Path source, final Path target) throws IOException {
checkNotNull(source);
checkNotNull(target);
DirectoryHelper.mkdir(target.getParent());
try {
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);
}
catch (UnsupportedOperationException e) { // NOSONAR
throw new AtomicMoveNotSupportedException(source.toString(), target.toString(), e.getMessage());
}
}
@Override
public void overwriteAtomic(final Path source, final Path target) throws IOException {
checkNotNull(source);
checkNotNull(target);
DirectoryHelper.mkdir(target.getParent());
try {
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
}
catch (UnsupportedOperationException e) { // NOSONAR
throw new AtomicMoveNotSupportedException(source.toString(), target.toString(), e.getMessage());
}
}
private void move(final Path source, final Path target) throws IOException {
if (supportsAtomicMove) {
try {
fileOperations.copyIfLocked(source, target, fileOperations::moveAtomic);
return;
}
catch (AtomicMoveNotSupportedException e) { // NOSONAR
supportsAtomicMove = false;
log.warn("Disabling atomic moves for blob store {}, could not move {} to {}, reason deleted: {}",
blobStoreConfiguration.getName(), source, target, e.getReason());
}
}
log.trace("Using normal move for blob store {}, moving {} to {}", blobStoreConfiguration.getName(), source, target);
fileOperations.copyIfLocked(source, target, fileOperations::move);
}
private void overwrite(final Path source, final Path target) throws IOException {
if (supportsAtomicMove) {
try {
fileOperations.copyIfLocked(source, target, fileOperations::overwriteAtomic);
return;
}
catch (AtomicMoveNotSupportedException e) { // NOSONAR
supportsAtomicMove = false;
log.warn("Disabling atomic moves for blob store {}, could not overwrite {} with {}, reason deleted: {}",
blobStoreConfiguration.getName(), source, target, e.getReason());
}
}
log.trace("Using normal overwrite for blob store {}, overwriting {} with {}", blobStoreConfiguration.getName(), source, target);
fileOperations.copyIfLocked(source, target, fileOperations::overwrite);
}
@Test
public void temporaryBlobMoveFallbackPersists() throws Exception {
final byte[] content = new byte[TEST_DATA_LENGTH];
new Random().nextBytes(content);
doThrow(new AtomicMoveNotSupportedException("", "", "")).when(fileOperations).moveAtomic(any(), any());
underTest.create(new ByteArrayInputStream(content), TEST_HEADERS);
underTest.create(new ByteArrayInputStream(content), TEST_HEADERS);
verify(fileOperations, times(1)).moveAtomic(any(), any());
verify(fileOperations, times(4)).move(any(), any());
}
static void move(Path source, Path target) throws IOException {
try {
Files.move(source, target, ATOMIC_MOVE, REPLACE_EXISTING);
} catch (AtomicMoveNotSupportedException ex) {
logger.debug(shortError, "-- move() - fallback, atomic move not supported: ", ex);
Files.move(source, target, REPLACE_EXISTING);
}
}
private void persistTemporaryFile() throws IOException {
final Path temporaryPath = file.temporaryFile().toPath();
final Path persistedPath = file.file().toPath();
try {
Files.move(temporaryPath, persistedPath, StandardCopyOption.ATOMIC_MOVE);
} catch (AtomicMoveNotSupportedException e) {
try {
Files.move(temporaryPath, persistedPath);
} catch (FileAlreadyExistsException ignored) {
LOGGER.debug("Snapshot {} was already previously completed", this);
}
}
}
/**
* Move a file atomically, if it fails, it falls back to a non-atomic operation
* @param from
* @param to
* @throws IOException
*/
private static void atomicMoveWithFallback(Path from, Path to) throws IOException
{
try
{
Files.move(from, to, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
}
catch (AtomicMoveNotSupportedException e)
{
logger.debug("Could not do an atomic move", e);
Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
}
}
@Override
public void setContents(InputStream input) throws IOException {
/*
* We write the new contents to a temporary file first, then move that
* file atomically to this file's location. This ensures that
* setContents() as a whole is atomic: should something go wrong, the
* file either has the old or new content, but never anything in
* between. Similarly, the stream returned by getContents() will never
* observe an inconsistent state while a setContents() is in progress.
*
* On Windows, this technique has the additional benefit of not having
* to open the "real" file, thus not locking it during the write.
*/
Path tempFilePath = Files.createTempFile(getName(), null);
if (input != null) {
Files.copy(input, tempFilePath, StandardCopyOption.REPLACE_EXISTING);
}
try {
Files.move(
tempFilePath,
toNioPath(),
StandardCopyOption.ATOMIC_MOVE,
StandardCopyOption.REPLACE_EXISTING);
} catch (AtomicMoveNotSupportedException e) {
Files.move(tempFilePath, toNioPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
public void copyOrMove( String cpOrMv, Path from, Path to, CopyOption... copyOptions ) throws IOException {
UnixSshPath unixFrom = checkPath( from );
UnixSshPath unixTo = checkPath( to );
Set<CopyOption> options = toSet( copyOptions );
if ( options.contains( StandardCopyOption.ATOMIC_MOVE ) ) {
throw new AtomicMoveNotSupportedException( from.toString(), to.toString(),
"to complicated to think about right now, try again at a later release." );
}
BasicFileAttributesImpl fromAttributes = new BasicFileAttributesImpl( unixFrom );
if ( exists( unixTo ) ) {
PosixFileAttributesImpl toAttributes = new PosixFileAttributesImpl( unixTo );
if ( fromAttributes.isSameFile( toAttributes ) ) return;
if ( options.contains( StandardCopyOption.REPLACE_EXISTING ) ) {
delete( unixTo, toAttributes );
}
else {
throw new FileAlreadyExistsException( to.toString() );
}
}
String command = unixFrom.getFileSystem().getCommand( cpOrMv )
+ " " + unixFrom.toAbsolutePath().quotedString()
+ " " + unixTo.toAbsolutePath().quotedString();
executeForStdout( unixTo, command );
}
private static boolean moveFile(Path source, Path target) throws IOException {
try {
Files.move(source, target,
StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
LOGGER.trace("Renamed file {} to {} with Files.move", source.toFile().getAbsolutePath(),
target.toFile().getAbsolutePath());
return true;
} catch (final AtomicMoveNotSupportedException ex) {
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
LOGGER.trace("Renamed file {} to {} with Files.move", source.toFile().getAbsolutePath(),
target.toFile().getAbsolutePath());
return true;
}
}
@SuppressWarnings("ConstantConditions")
public static boolean atomicMoveFile(final File source, final File target) throws IOException {
// Move temp file to target path atomically.
// The code comes from https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/util/AtomicFileWriter.java#L187
Requires.requireNonNull(source, "source");
Requires.requireNonNull(target, "target");
final Path sourcePath = source.toPath();
final Path targetPath = target.toPath();
try {
return Files.move(sourcePath, targetPath, StandardCopyOption.ATOMIC_MOVE) != null;
} catch (final IOException e) {
// If it falls here that can mean many things. Either that the atomic move is not supported,
// or something wrong happened. Anyway, let's try to be over-diagnosing
if (e instanceof AtomicMoveNotSupportedException) {
LOG.warn("Atomic move not supported. falling back to non-atomic move, error: {}.", e.getMessage());
} else {
LOG.warn("Unable to move atomically, falling back to non-atomic move, error: {}.", e.getMessage());
}
if (target.exists()) {
LOG.info("The target file {} was already existing.", targetPath);
}
try {
return Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING) != null;
} catch (final IOException e1) {
e1.addSuppressed(e);
LOG.warn("Unable to move {} to {}. Attempting to delete {} and abandoning.", sourcePath, targetPath,
sourcePath);
try {
Files.deleteIfExists(sourcePath);
} catch (final IOException e2) {
e2.addSuppressed(e1);
LOG.warn("Unable to delete {}, good bye then!", sourcePath);
throw e2;
}
throw e1;
}
}
}