Sharku
Sharku

Reputation: 1092

What is the best way to check if a directory and its content is locked?

Suppose I pass a string containing the path to a directory to a random method. Before this method starts working it should check if the directory or any of its content is locked. I thought this would be a simple task, but turned out I got some hardly simple code to do it. Do you have any suggestions how to improve it or at least make it shorter?

If you think that is already the best solution just give it an up vote and go on solving real problems :P

public static boolean checkLocks(String path) {

    File f = new File(path);

    if(f.isDirectory()) {
        boolean ans = true;;
        String files[] = f.list();

        for (String file : files) {
            File ff = new File(f, file);
            ans = checkLocks(ff.toString());
            if(!ans){
                break;
            }
        }
        return ans;
    } else {
        try {
            RandomAccessFile stream = new RandomAccessFile(path, "rw");
            FileChannel channel = stream.getChannel();

            FileLock lock = null;
            try {
                lock = channel.tryLock();
            } catch (final OverlappingFileLockException e) {
                stream.close();
                channel.close();
                System.out.println("File at "+path+" locked");
                return false;
            }
            stream.close();
            channel.close();
            return true;

        } catch (IOException eio) {
            System.out.println("File at "+path+" does not exits");
            return false;
        }
    }

}

Upvotes: 1

Views: 853

Answers (3)

Shrawan Kumar
Shrawan Kumar

Reputation: 11

I would suggest you to use SimpleFileVistor class instead of writing a code to walk through directory.

There is already built in method in Files class to walk through the directory.

Files.walkFileTree(path, MyFileVisitor)

You can create a customer visitor class like

public class MyFileVisitor  extends SimpleFileVisitor<Path>{


    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
            throws IOException {
        System.out.println("Visit  the File")
      return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc)
            throws IOException {
        System.out.println("File Visit Failed")
      return FileVisitResult.CONTINUE;
    }
}

This can improve your code readability and it is less verbose.

Upvotes: 1

DavidW
DavidW

Reputation: 1421

Checking each file in the directory strikes me as slow and prone to race conditions. In your example you're getting a list of files in the directory at an instant and then you test each; meanwhile the creator thread may still be adding files. Even if every file in your list is accessible, the creator may not be finished writing the directory.

It's somewhat old-school and not very fancy but I would use either a temporary directory name while creation is in progress or write a lockfile as the first file and delete it when the creator is finished.

In the first case:

String baseDirectory = "{whatever}";
String workDirectory = "workDirectory" + counter;
Path tempPath = FileSystems.getDefault().getPath(baseDirectory, ".temp_" + workDirectory);
Path workPath = FileSystems.getDefault().getPath(baseDirectory, workDirectory);
Files.createDirectory(tempPath);
// Write the contents of the directory.
// [...]
Files.move(tempPath, workPath, CopyOptions.ATOMIC_MOVE);

In the second case:

String baseDirectory = "{whatever}";
String workDirectory = "workDirectory" + counter;
Path workPath = FileSystems.getDefault().getPath(baseDirectory, workDirectory);
Files.createDirectory(workPath);
Path lockFile = workPath.resolve("LOCKFILE");
Files.createFile(lockFile);
// Write the contents of the directory.
// [...]
Files.delete(lockFile);

The idea in both cases is that the creator task explicitly signals when it's done creating the directory. If you just wait for a pause in operations, it could just be waiting for a large buffer to load over the network.

Upvotes: 1

codemusings
codemusings

Reputation: 117

I think the easiest way is to use the Files class and its is* methods like isReadable and isWritable.

if (Files.isReadable(new File(filepath).toPath()) &&
    Files.isWritable(new File(filepath).toPath()))
{
    /* do something... */
}

Should work for regular files and folders.

Upvotes: 1

Related Questions