You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by si...@apache.org on 2018/05/17 09:07:08 UTC

lucene-solr:branch_7x: LUCENE-8318: Ensure pending delete is not brought back on a try delete attempt

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_7x b6b305000 -> b178321bd


LUCENE-8318: Ensure pending delete is not brought back on a try delete attempt

When renaming a file, `FSDirectory#rename` tries to delete the dest file
if it's in the pending deletes list. If that delete fails, it adds the
dest to the pending deletes list again. This causes the dest file to be
deleted later by `deletePendingFiles`.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/b178321b
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/b178321b
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/b178321b

Branch: refs/heads/branch_7x
Commit: b178321bd1b0198532f70e2413b1e7d935556042
Parents: b6b3050
Author: Simon Willnauer <si...@apache.org>
Authored: Thu May 17 09:15:31 2018 +0200
Committer: Simon Willnauer <si...@apache.org>
Committed: Thu May 17 11:03:04 2018 +0200

----------------------------------------------------------------------
 .../org/apache/lucene/store/FSDirectory.java    |  2 +
 .../lucene/store/TestSimpleFSDirectory.java     | 48 ++++++++++++++++++++
 .../org/apache/lucene/mockfile/WindowsFS.java   | 30 +++++++++---
 3 files changed, 73 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b178321b/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java b/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java
index 111352e..fb03f85 100644
--- a/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java
+++ b/lucene/core/src/java/org/apache/lucene/store/FSDirectory.java
@@ -250,6 +250,7 @@ public abstract class FSDirectory extends BaseDirectory {
     // If this file was pending delete, we are now bringing it back to life:
     if (pendingDeletes.remove(name)) {
       privateDeleteFile(name, true); // try again to delete it - this is best effort
+      pendingDeletes.remove(name); // watch out - if the delete fails it put
     }
     return new FSIndexOutput(name);
   }
@@ -297,6 +298,7 @@ public abstract class FSDirectory extends BaseDirectory {
     maybeDeletePendingFiles();
     if (pendingDeletes.remove(dest)) {
       privateDeleteFile(dest, true); // try again to delete it - this is best effort
+      pendingDeletes.remove(dest); // watch out if the delete fails it's back in here.
     }
     Files.move(directory.resolve(source), directory.resolve(dest), StandardCopyOption.ATOMIC_MOVE);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b178321b/lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java b/lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java
index eb82571..e550bcc 100644
--- a/lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java
+++ b/lucene/core/src/test/org/apache/lucene/store/TestSimpleFSDirectory.java
@@ -18,8 +18,14 @@ package org.apache.lucene.store;
 
 
 import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
 import java.nio.file.Path;
 
+import org.apache.lucene.mockfile.FilterPath;
+import org.apache.lucene.mockfile.WindowsFS;
+import org.apache.lucene.util.IOUtils;
+
 /**
  * Tests SimpleFSDirectory
  */
@@ -29,4 +35,46 @@ public class TestSimpleFSDirectory extends BaseDirectoryTestCase {
   protected Directory getDirectory(Path path) throws IOException {
     return new SimpleFSDirectory(path);
   }
+
+  public void testRenameWithPendingDeletes() throws IOException {
+    Path path = createTempDir();
+    // Use WindowsFS to prevent open files from being deleted:
+    FileSystem fs = new WindowsFS(path.getFileSystem()).getFileSystem(URI.create("file:///"));
+    Path root = new FilterPath(path, fs);
+    Directory directory = getDirectory(root);
+    IndexOutput output = directory.createOutput("target.txt", IOContext.DEFAULT);
+    output.writeInt(1);
+    output.close();
+    IndexOutput output1 = directory.createOutput("source.txt", IOContext.DEFAULT);
+    output1.writeInt(2);
+    output1.close();
+
+    IndexInput input = directory.openInput("target.txt", IOContext.DEFAULT);
+    directory.deleteFile("target.txt");
+    directory.rename("source.txt", "target.txt");
+    IndexInput input1 = directory.openInput("target.txt", IOContext.DEFAULT);
+    assertTrue(directory.getPendingDeletions().isEmpty());
+    assertEquals(1, input.readInt());
+    assertEquals(2, input1.readInt());
+    IOUtils.close(input1, input, directory);
+  }
+
+  public void testCreateOutputWithPendingDeletes() throws IOException {
+    Path path = createTempDir();
+    // Use WindowsFS to prevent open files from being deleted:
+    FileSystem fs = new WindowsFS(path.getFileSystem()).getFileSystem(URI.create("file:///"));
+    Path root = new FilterPath(path, fs);
+    Directory directory = getDirectory(root);
+    IndexOutput output = directory.createOutput("file.txt", IOContext.DEFAULT);
+    output.writeInt(1);
+    output.close();
+    IndexInput input = directory.openInput("file.txt", IOContext.DEFAULT);
+    directory.deleteFile("file.txt");
+    expectThrows(IOException.class, () -> {
+      directory.createOutput("file.txt", IOContext.DEFAULT);
+    });
+    assertTrue(directory.getPendingDeletions().isEmpty());
+    assertEquals(1, input.readInt());
+    IOUtils.close(input, directory);
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b178321b/lucene/test-framework/src/java/org/apache/lucene/mockfile/WindowsFS.java
----------------------------------------------------------------------
diff --git a/lucene/test-framework/src/java/org/apache/lucene/mockfile/WindowsFS.java b/lucene/test-framework/src/java/org/apache/lucene/mockfile/WindowsFS.java
index b7b5457..5efc725 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/mockfile/WindowsFS.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/mockfile/WindowsFS.java
@@ -88,19 +88,22 @@ public class WindowsFS extends HandleTrackingFS {
       }
     }
   }
+
+  private Object getKeyOrNull(Path path) {
+    try {
+      return getKey(path);
+    } catch (Exception ignore) {
+      // we don't care if the file doesn't exist
+    }
+    return null;
+  }
   
   /** 
    * Checks that it's ok to delete {@code Path}. If the file
    * is still open, it throws IOException("access denied").
    */
   private void checkDeleteAccess(Path path) throws IOException {
-    Object key = null;
-    try {
-      key = getKey(path);
-    } catch (Throwable ignore) {
-      // we don't care if the file doesn't exist
-    } 
-
+    Object key = getKeyOrNull(path);
     if (key != null) {
       synchronized(openFiles) {
         if (openFiles.containsKey(key)) {
@@ -122,7 +125,20 @@ public class WindowsFS extends HandleTrackingFS {
   public void move(Path source, Path target, CopyOption... options) throws IOException {
     synchronized (openFiles) {
       checkDeleteAccess(source);
+      Object key = getKeyOrNull(target);
       super.move(source, target, options);
+      if (key != null) {
+        Object newKey = getKey(target);
+        if (newKey.equals(key) == false) {
+          // we need to transfer ownership here if we have open files on this file since the getKey() method will
+          // return a different i-node next time we call it with the target path and our onClose method will
+          // trip an assert
+          Integer remove = openFiles.remove(key);
+          if (remove != null) {
+            openFiles.put(newKey, remove);
+          }
+        }
+      }
     }
   }