133 lines
3.1 KiB
Java
133 lines
3.1 KiB
Java
package net.minecraft.util;
|
|
|
|
import com.google.common.base.Charsets;
|
|
import java.io.IOException;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.channels.FileChannel;
|
|
import java.nio.channels.FileLock;
|
|
import java.nio.file.AccessDeniedException;
|
|
import java.nio.file.NoSuchFileException;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.StandardOpenOption;
|
|
import net.minecraft.FileUtil;
|
|
|
|
public class DirectoryLock implements AutoCloseable {
|
|
public static final String LOCK_FILE = "session.lock";
|
|
private final FileChannel lockFile;
|
|
private final FileLock lock;
|
|
private static final ByteBuffer DUMMY;
|
|
|
|
public static DirectoryLock create(Path path) throws IOException {
|
|
Path path2 = path.resolve("session.lock");
|
|
FileUtil.createDirectoriesSafe(path);
|
|
FileChannel fileChannel = FileChannel.open(path2, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
|
|
|
|
try {
|
|
fileChannel.write(DUMMY.duplicate());
|
|
fileChannel.force(true);
|
|
FileLock fileLock = fileChannel.tryLock();
|
|
if (fileLock == null) {
|
|
throw DirectoryLock.LockException.alreadyLocked(path2);
|
|
} else {
|
|
return new DirectoryLock(fileChannel, fileLock);
|
|
}
|
|
} catch (IOException var6) {
|
|
try {
|
|
fileChannel.close();
|
|
} catch (IOException var5) {
|
|
var6.addSuppressed(var5);
|
|
}
|
|
|
|
throw var6;
|
|
}
|
|
}
|
|
|
|
private DirectoryLock(FileChannel lockFile, FileLock lock) {
|
|
this.lockFile = lockFile;
|
|
this.lock = lock;
|
|
}
|
|
|
|
public void close() throws IOException {
|
|
try {
|
|
if (this.lock.isValid()) {
|
|
this.lock.release();
|
|
}
|
|
} finally {
|
|
if (this.lockFile.isOpen()) {
|
|
this.lockFile.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean isValid() {
|
|
return this.lock.isValid();
|
|
}
|
|
|
|
public static boolean isLocked(Path path) throws IOException {
|
|
Path path2 = path.resolve("session.lock");
|
|
|
|
try {
|
|
FileChannel fileChannel = FileChannel.open(path2, StandardOpenOption.WRITE);
|
|
|
|
boolean var4;
|
|
try {
|
|
FileLock fileLock = fileChannel.tryLock();
|
|
|
|
try {
|
|
var4 = fileLock == null;
|
|
} catch (Throwable var8) {
|
|
if (fileLock != null) {
|
|
try {
|
|
fileLock.close();
|
|
} catch (Throwable var7) {
|
|
var8.addSuppressed(var7);
|
|
}
|
|
}
|
|
|
|
throw var8;
|
|
}
|
|
|
|
if (fileLock != null) {
|
|
fileLock.close();
|
|
}
|
|
} catch (Throwable var9) {
|
|
if (fileChannel != null) {
|
|
try {
|
|
fileChannel.close();
|
|
} catch (Throwable var6) {
|
|
var9.addSuppressed(var6);
|
|
}
|
|
}
|
|
|
|
throw var9;
|
|
}
|
|
|
|
if (fileChannel != null) {
|
|
fileChannel.close();
|
|
}
|
|
|
|
return var4;
|
|
} catch (AccessDeniedException var10) {
|
|
return true;
|
|
} catch (NoSuchFileException var11) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static {
|
|
byte[] bs = "☃".getBytes(Charsets.UTF_8);
|
|
DUMMY = ByteBuffer.allocateDirect(bs.length);
|
|
DUMMY.put(bs);
|
|
DUMMY.flip();
|
|
}
|
|
|
|
public static class LockException extends IOException {
|
|
private LockException(Path path, String message) {
|
|
super(path.toAbsolutePath() + ": " + message);
|
|
}
|
|
|
|
public static DirectoryLock.LockException alreadyLocked(Path path) {
|
|
return new DirectoryLock.LockException(path, "already locked (possibly by other Minecraft instance?)");
|
|
}
|
|
}
|
|
}
|