Index: FSDirectory.java =================================================================== --- FSDirectory.java (revision 436723) +++ FSDirectory.java (working copy) @@ -35,6 +35,12 @@ */ public class FSDirectory extends Directory { + /** + * millisecnds to wait before retrying an IO operation that failed due to perhaps + * a temporary instability of the File System or the Operating System. + */ + private static final int ACCESS_ERROR_RETRY_DELAY = 30; + /** This cache of directories ensures that there is a unique Directory * instance per path, so that synchronization on the Directory can be used to * synchronize access between readers and writers. @@ -182,7 +188,21 @@ } private synchronized void create() throws IOException { - if (!directory.exists()) + try { + doCreate(); + } catch (IOException e) { + if (isAccessError(e)) { + waitDueToAccessError(); + System.out.println("bypass weird OS/FS bug (create)"); + doCreate(); + } else { + throw e; + } + } + } + + private void doCreate() throws IOException { + if (!directory.exists()) if (!directory.mkdirs()) throw new IOException("Cannot create directory: " + directory); @@ -256,7 +276,21 @@ /** Renames an existing file in the directory. */ public synchronized void renameFile(String from, String to) throws IOException { - File old = new File(directory, from); + try { + doRenameFile(from, to); + } catch (IOException e) { + if (isAccessError(e)) { + waitDueToAccessError(); + System.out.println("bypass weird OS/FS bug (renameFile)"); + doRenameFile(from, to); + } else { + throw e; + } + } + } + + private void doRenameFile(String from, String to) throws IOException { + File old = new File(directory, from); File nu = new File(directory, to); /* This is not atomic. If the program crashes between the call to @@ -324,14 +358,54 @@ if (file.exists() && !file.delete()) // delete existing, if any throw new IOException("Cannot overwrite: " + file); - return new FSIndexOutput(file); + try { + return new FSIndexOutput(file); + } catch (IOException e) { + if (isAccessError(e)) { + waitDueToAccessError(); + System.out.println("bypass weird OS/FS bug (createOutput)"); + return new FSIndexOutput(file); + } + throw e; + } } /** Returns a stream reading an existing file. */ public IndexInput openInput(String name) throws IOException { - return new FSIndexInput(new File(directory, name)); + try { + return new FSIndexInput(new File(directory, name)); + } catch (IOException e) { + if (isAccessError(e)) { + waitDueToAccessError(); + System.out.println("bypass weird OS/FS bug (openInput)"); + return new FSIndexInput(new File(directory, name)); + } + throw e; + } + } + /** wait a short time, befiore retrying an io operation, to bypass weird OS/FS bug */ + private void waitDueToAccessError() { + try { + Thread.sleep(ACCESS_ERROR_RETRY_DELAY); + } catch (InterruptedException ie) { + } + } + + private static boolean isAccessError(Throwable e) { + Throwable t = e; + int depth=0; + while (t!=null && depth++<10) { + if (t.getMessage()!=null && t.getMessage().toLowerCase().contains("access")) + return true; + t = t.getCause(); + if (t==e) + break; + } + return false; + } + /** * So we can do some byte-to-hexchar conversion below */ @@ -363,12 +437,29 @@ } } - return lockFile.createNewFile(); + try { + return lockFile.createNewFile(); + } catch (IOException e) { + if (isAccessError(e)) { + waitDueToAccessError(); + System.out.println("bypass weird OS/FS bug (lock.createNewFile)"); + return lockFile.createNewFile(); + } + throw e; + } } public void release() { if (disableLocks) return; - lockFile.delete(); + try { + lockFile.delete(); + } catch (Throwable t) { + if (isAccessError(t)) { + waitDueToAccessError(); + System.out.println("bypass weird OS/FS bug (lock.delete)"); + lockFile.delete(); + } + } } public boolean isLocked() { if (disableLocks)