提交 bd00e7d3 authored 作者: Thomas Mueller's avatar Thomas Mueller

Improved compatibility with the Java 7 FileSystem abstraction.

上级 abc9cec3
...@@ -54,6 +54,7 @@ public class FileStore { ...@@ -54,6 +54,7 @@ public class FileStore {
private String mode; private String mode;
private TempFileDeleter tempFileDeleter; private TempFileDeleter tempFileDeleter;
private boolean textMode; private boolean textMode;
private java.nio.channels.FileLock lock;
/** /**
* Create a new file using the given settings. * Create a new file using the given settings.
...@@ -492,16 +493,27 @@ public class FileStore { ...@@ -492,16 +493,27 @@ public class FileStore {
* *
* @return true if successful * @return true if successful
*/ */
public boolean tryLock() { public synchronized boolean tryLock() {
return file.tryLock(); try {
lock = file.tryLock();
return true;
} catch (IOException e) {
// ignore
return false;
}
} }
/** /**
* Release the file lock. * Release the file lock.
*/ */
public void releaseLock() { public synchronized void releaseLock() {
if (file != null) { if (file != null && lock != null) {
file.releaseLock(); try {
lock.release();
} catch (IOException e) {
// ignore
}
lock = null;
} }
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.store.fs; package org.h2.store.fs;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.FileLock;
/** /**
* This interface represents a random access file. * This interface represents a random access file.
...@@ -71,13 +72,8 @@ public interface FileObject { ...@@ -71,13 +72,8 @@ public interface FileObject {
/** /**
* Try to lock the file exclusively. * Try to lock the file exclusively.
* *
* @return true if locking was successful * @return a lock object if successful, or null if not
*/ */
boolean tryLock(); FileLock tryLock() throws IOException;
/**
* Release the file lock.
*/
void releaseLock();
} }
...@@ -19,7 +19,6 @@ public class FileObjectDisk implements FileObject { ...@@ -19,7 +19,6 @@ public class FileObjectDisk implements FileObject {
private final RandomAccessFile file; private final RandomAccessFile file;
private final String name; private final String name;
private FileLock lock;
FileObjectDisk(String fileName, String mode) throws FileNotFoundException { FileObjectDisk(String fileName, String mode) throws FileNotFoundException {
this.file = new RandomAccessFile(fileName, mode); this.file = new RandomAccessFile(fileName, mode);
...@@ -48,27 +47,8 @@ public class FileObjectDisk implements FileObject { ...@@ -48,27 +47,8 @@ public class FileObjectDisk implements FileObject {
} }
} }
public synchronized boolean tryLock() { public synchronized FileLock tryLock() throws IOException {
if (lock == null) { return file.getChannel().tryLock();
try {
lock = file.getChannel().tryLock();
} catch (Exception e) {
// could not lock (OverlappingFileLockException)
}
return lock != null;
}
return false;
}
public synchronized void releaseLock() {
if (lock != null) {
try {
lock.release();
} catch (IOException e) {
// ignore
}
lock = null;
}
} }
public void close() throws IOException { public void close() throws IOException {
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.store.fs; package org.h2.store.fs;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.FileLock;
/** /**
* This class represents an in-memory file. * This class represents an in-memory file.
...@@ -60,12 +61,8 @@ public class FileObjectMem implements FileObject { ...@@ -60,12 +61,8 @@ public class FileObjectMem implements FileObject {
// do nothing // do nothing
} }
public boolean tryLock() { public FileLock tryLock() {
return data.tryLock(); return null;
}
public void releaseLock() {
data.releaseLock();
} }
} }
...@@ -22,7 +22,6 @@ public class FileObjectNio implements FileObject { ...@@ -22,7 +22,6 @@ public class FileObjectNio implements FileObject {
private final String name; private final String name;
private final RandomAccessFile file; private final RandomAccessFile file;
private final FileChannel channel; private final FileChannel channel;
private FileLock lock;
private long length; private long length;
FileObjectNio(String fileName, String mode) throws IOException { FileObjectNio(String fileName, String mode) throws IOException {
...@@ -94,27 +93,8 @@ public class FileObjectNio implements FileObject { ...@@ -94,27 +93,8 @@ public class FileObjectNio implements FileObject {
} }
} }
public synchronized boolean tryLock() { public synchronized FileLock tryLock() throws IOException {
if (lock == null) { return channel.tryLock();
try {
lock = channel.tryLock();
} catch (IOException e) {
// could not lock
}
return lock != null;
}
return false;
}
public synchronized void releaseLock() {
if (lock != null) {
try {
lock.release();
} catch (IOException e) {
// ignore
}
lock = null;
}
} }
public String toString() { public String toString() {
......
...@@ -28,7 +28,6 @@ public class FileObjectNioMapped implements FileObject { ...@@ -28,7 +28,6 @@ public class FileObjectNioMapped implements FileObject {
private final MapMode mode; private final MapMode mode;
private RandomAccessFile file; private RandomAccessFile file;
private MappedByteBuffer mapped; private MappedByteBuffer mapped;
private FileLock lock;
/** /**
* The position within the file. Can't use the position of the mapped buffer * The position within the file. Can't use the position of the mapped buffer
...@@ -202,27 +201,8 @@ public class FileObjectNioMapped implements FileObject { ...@@ -202,27 +201,8 @@ public class FileObjectNioMapped implements FileObject {
pos += len; pos += len;
} }
public synchronized boolean tryLock() { public synchronized FileLock tryLock() throws IOException {
if (lock == null) { return file.getChannel().tryLock();
try {
lock = file.getChannel().tryLock();
} catch (IOException e) {
// could not lock
}
return lock != null;
}
return false;
}
public synchronized void releaseLock() {
if (lock != null) {
try {
lock.release();
} catch (IOException e) {
// ignore
}
lock = null;
}
} }
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.store.fs; package org.h2.store.fs;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.FileLock;
/** /**
* A file object that records all write operations and can re-play them. * A file object that records all write operations and can re-play them.
...@@ -62,12 +63,8 @@ public class FileObjectRec implements FileObject { ...@@ -62,12 +63,8 @@ public class FileObjectRec implements FileObject {
fs.log(Recorder.WRITE, name, buff, file.position()); fs.log(Recorder.WRITE, name, buff, file.position());
} }
public boolean tryLock() { public FileLock tryLock() throws IOException {
return file.tryLock(); return file.tryLock();
} }
public void releaseLock() {
file.releaseLock();
}
} }
\ No newline at end of file
...@@ -8,6 +8,7 @@ package org.h2.store.fs; ...@@ -8,6 +8,7 @@ package org.h2.store.fs;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.FileLock;
import org.h2.message.DbException; import org.h2.message.DbException;
/** /**
...@@ -153,12 +154,8 @@ public class FileObjectSplit implements FileObject { ...@@ -153,12 +154,8 @@ public class FileObjectSplit implements FileObject {
return l; return l;
} }
public boolean tryLock() { public FileLock tryLock() throws IOException {
return list[0].tryLock(); return list[0].tryLock();
} }
public void releaseLock() {
list[0].releaseLock();
}
} }
...@@ -9,6 +9,7 @@ package org.h2.store.fs; ...@@ -9,6 +9,7 @@ package org.h2.store.fs;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.channels.FileLock;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
...@@ -103,12 +104,8 @@ public class FileObjectZip implements FileObject { ...@@ -103,12 +104,8 @@ public class FileObjectZip implements FileObject {
throw new IOException("File is read-only"); throw new IOException("File is read-only");
} }
public boolean tryLock() { public FileLock tryLock() {
return false; return null;
}
public void releaseLock() {
// ignore
} }
} }
...@@ -29,7 +29,7 @@ public abstract class FilePath { ...@@ -29,7 +29,7 @@ public abstract class FilePath {
private static Map<String, FilePath> providers; private static Map<String, FilePath> providers;
/** /**
* The prefix for temporary files. See also TestClearReferences. * The prefix for temporary files.
*/ */
private static String tempRandom; private static String tempRandom;
private static long tempSequence; private static long tempSequence;
......
...@@ -15,7 +15,7 @@ import java.io.IOException; ...@@ -15,7 +15,7 @@ import java.io.IOException;
public class FilePathNio extends FilePathWrapper { public class FilePathNio extends FilePathWrapper {
public FileObject openFileObject(String mode) throws IOException { public FileObject openFileObject(String mode) throws IOException {
return new FileObjectNio(name, mode); return new FileObjectNio(name.substring(getScheme().length() + 1), mode);
} }
public String getScheme() { public String getScheme() {
......
...@@ -15,7 +15,7 @@ import java.io.IOException; ...@@ -15,7 +15,7 @@ import java.io.IOException;
public class FilePathNioMapped extends FilePathNio { public class FilePathNioMapped extends FilePathNio {
public FileObject openFileObject(String mode) throws IOException { public FileObject openFileObject(String mode) throws IOException {
return new FileObjectNioMapped(name, mode); return new FileObjectNioMapped(name.substring(getScheme().length() + 1), mode);
} }
public String getScheme() { public String getScheme() {
......
...@@ -324,322 +324,4 @@ public class FileUtils { ...@@ -324,322 +324,4 @@ public class FileUtils {
return FilePath.get(prefix).createTempFile(suffix, deleteOnExit, inTempDir).toString(); return FilePath.get(prefix).createTempFile(suffix, deleteOnExit, inTempDir).toString();
} }
// /**
// * Checks if a file exists.
// * This method is similar to Java 7 <code>java.nio.file.Path.exists</code>.
// *
// * @param fileName the file name
// * @return true if it exists
// */
// public static boolean exists(String fileName) {
// return getFileSystem(fileName).exists(fileName);
// }
//
// /**
// * Create a directory (all required parent directories must already exist).
// * This method is similar to Java 7 <code>java.nio.file.Path.createDirectory</code>.
// *
// * @param directoryName the directory name
// */
// public static void createDirectory(String directoryName) {
// getFileSystem(directoryName).createDirectory(directoryName);
// }
//
// /**
// * Create a new file.
// * This method is similar to Java 7 <code>java.nio.file.Path.createFile</code>, but returns
// * false instead of throwing a exception if the file already existed.
// *
// * @param fileName the file name
// * @return true if creating was successful
// */
// public static boolean createFile(String fileName) {
// return getFileSystem(fileName).createFile(fileName);
// }
//
// /**
// * Delete a file or directory if it exists.
// * Directories may only be deleted if they are empty.
// * This method is similar to Java 7 <code>java.nio.file.Path.deleteIfExists</code>.
// *
// * @param path the file or directory name
// */
// public static void delete(String path) {
// getFileSystem(path).delete(path);
// }
//
// /**
// * Normalize a file name.
// * This method is similar to Java 7 <code>java.nio.file.Path.toRealPath</code>.
// *
// * @param fileName the file name
// * @return the normalized file name
// */
// public static String getCanonicalPath(String fileName) {
// return getFileSystem(fileName).getCanonicalPath(fileName);
// }
//
// /**
// * Get the parent directory of a file or directory.
// * This method is similar to Java 7 <code>java.nio.file.Path.getParent</code>.
// *
// * @param fileName the file or directory name
// * @return the parent directory name
// */
// public static String getParent(String fileName) {
// return getFileSystem(fileName).getParent(fileName);
// }
//
// /**
// * Check if the file name includes a path.
// * This method is similar to Java 7 <code>java.nio.file.Path.isAbsolute</code>.
// *
// * @param fileName the file name
// * @return if the file name is absolute
// */
// public static boolean isAbsolute(String fileName) {
// return getFileSystem(fileName).isAbsolute(fileName);
// }
//
// /**
// * Rename a file if this is allowed.
// * This method is similar to Java 7 <code>java.nio.file.Path.moveTo</code>.
// *
// * @param oldName the old fully qualified file name
// * @param newName the new fully qualified file name
// */
// public static void moveTo(String oldName, String newName) {
// getFileSystem(oldName).moveTo(oldName, newName);
// }
//
// /**
// * Get the file or directory name (the last element of the path).
// * This method is similar to Java 7 <code>java.nio.file.Path.getName</code>.
// *
// * @param path the directory and file name
// * @return just the file name
// */
// public static String getName(String path) {
// return getFileSystem(path).getName(path);
// }
//
// /**
// * List the files in the given directory.
// * This method is similar to Java 7 <code>java.nio.file.Path.newDirectoryStream</code>.
// *
// * @param path the directory
// * @return the list of fully qualified file names
// */
// public static String[] listFiles(String path) {
// return getFileSystem(path).listFiles(path);
// }
//
// /**
// * Get the last modified date of a file.
// * This method is similar to Java 7
// * <code>java.nio.file.attribute.Attributes.readBasicFileAttributes(file).lastModified().toMillis()</code>
// *
// * @param fileName the file name
// * @return the last modified date
// */
// public static long lastModified(String fileName) {
// return getFileSystem(fileName).lastModified(fileName);
// }
//
// /**
// * Get the size of a file in bytes
// * This method is similar to Java 7
// * <code>java.nio.file.attribute.Attributes.readBasicFileAttributes(file).size()</code>
// *
// * @param fileName the file name
// * @return the size in bytes
// */
// public static long size(String fileName) {
// return getFileSystem(fileName).size(fileName);
// }
//
// /**
// * Check if it is a file or a directory.
// * <code>java.nio.file.attribute.Attributes.readBasicFileAttributes(file).isDirectory()</code>
// *
// * @param fileName the file or directory name
// * @return true if it is a directory
// */
// public static boolean isDirectory(String fileName) {
// return getFileSystem(fileName).isDirectory(fileName);
// }
//
// /**
// * Open a random access file object.
// * This method is similar to Java 7 <code>java.nio.channels.FileChannel.open</code>.
// *
// * @param fileName the file name
// * @param mode the access mode. Supported are r, rw, rws, rwd
// * @return the file object
// */
// public static FileObject openFileObject(String fileName, String mode) throws IOException {
// return getFileSystem(fileName).openFileObject(fileName, mode);
// }
//
// /**
// * Create an input stream to read from the file.
// * This method is similar to Java 7 <code>java.nio.file.Path.newInputStream</code>.
// *
// * @param fileName the file name
// * @return the input stream
// */
// public static InputStream newInputStream(String fileName) throws IOException {
// return getFileSystem(fileName).newInputStream(fileName);
// }
//
// /**
// * Create an output stream to write into the file.
// * This method is similar to Java 7 <code>java.nio.file.Path.newOutputStream</code>.
// *
// * @param fileName the file name
// * @param append if true, the file will grow, if false, the file will be
// * truncated first
// * @return the output stream
// */
// public static OutputStream newOutputStream(String fileName, boolean append) {
// return getFileSystem(fileName).newOutputStream(fileName, append);
// }
//
// /**
// * Check if the file is writable.
// * This method is similar to Java 7
// * <code>java.nio.file.Path.checkAccess(AccessMode.WRITE)</code>
// *
// * @param fileName the file name
// * @return if the file is writable
// */
// public static boolean canWrite(String fileName) {
// return getFileSystem(fileName).canWrite(fileName);
// }
//
// // special methods =======================================
//
// /**
// * Disable the ability to write. The file can still be deleted afterwards.
// *
// * @param fileName the file name
// * @return true if the call was successful
// */
// public static boolean setReadOnly(String fileName) {
// return getFileSystem(fileName).setReadOnly(fileName);
// }
//
// /**
// * Get the unwrapped file name (without wrapper prefixes if wrapping /
// * delegating file systems are used).
// *
// * @param fileName the file name
// * @return the unwrapped
// */
// public static String unwrap(String fileName) {
// return getFileSystem(fileName).unwrap(fileName);
// }
//
// /**
// * Check if a file starts with a given prefix.
// *
// * @param fileName the complete file name
// * @param prefix the prefix
// * @return true if it starts with the prefix
// */
// public static boolean fileStartsWith(String fileName, String prefix) {
// return getFileSystem(fileName).fileStartsWith(fileName, prefix);
// }
//
// /**
// * Create a new temporary file.
// *
// * @param prefix the prefix of the file name (including directory name if
// * required)
// * @param suffix the suffix
// * @param deleteOnExit if the file should be deleted when the virtual
// * machine exists
// * @param inTempDir if the file should be stored in the temporary directory
// * @return the name of the created file
// */
// public static String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
// throws IOException {
// return getFileSystem(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir);
// }
//
// // utility methods =======================================
//
// /**
// * Delete a directory or file and all subdirectories and files.
// *
// * @param path the path
// * @param tryOnly whether errors should be ignored
// */
// public static void deleteRecursive(String path, boolean tryOnly) {
// if (exists(path)) {
// if (FileUtils.isDirectory(path)) {
// for (String s : FileUtils.listFiles(path)) {
// deleteRecursive(s, tryOnly);
// }
// }
// if (tryOnly) {
// FileUtils.tryDelete(path);
// } else {
// delete(path);
// }
// }
// }
//
// /**
// * Create the directory and all required parent directories.
// *
// * @param dir the directory name
// */
// public static void createDirectories(String dir) {
// if (dir != null) {
// if (FileUtils.exists(dir)) {
// if (!FileUtils.isDirectory(dir)) {
// DbException.get(ErrorCode.FILE_CREATION_FAILED_1,
// "Could not create directory, " +
// "because a file with the same name already exists: " + dir);
// }
// } else {
// String parent = FileUtils.getParent(dir);
// createDirectories(parent);
// createDirectory(dir);
// }
// }
// }
//
// /**
// * Copy a file from one directory to another, or to another file.
// *
// * @param original the original file name
// * @param copy the file name of the copy
// */
// public static void copy(String original, String copy) throws IOException {
// InputStream in = FileUtils.newInputStream(original);
// OutputStream out = FileUtils.newOutputStream(copy, false);
// IOUtils.copyAndClose(in, out);
// }
//
// private static FileSystem getFileSystem(String fileName) {
// return FileSystem.getInstance(fileName);
// }
//
// /**
// * Try to delete a file (ignore errors).
// *
// * @param fileName the file name
// * @return true if it worked
// */
// public static boolean tryDelete(String fileName) {
// try {
// getFileSystem(fileName).delete(fileName);
// return true;
// } catch (Exception e) {
// return false;
// }
// }
} }
...@@ -12,6 +12,7 @@ import java.io.IOException; ...@@ -12,6 +12,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
...@@ -112,9 +113,11 @@ public class TestFileSystem extends TestBase { ...@@ -112,9 +113,11 @@ public class TestFileSystem extends TestBase {
FileObject o = FileUtils.openFileObject(f, "rw"); FileObject o = FileUtils.openFileObject(f, "rw");
o.position(4000); o.position(4000);
o.write(new byte[1], 0, 1); o.write(new byte[1], 0, 1);
o.tryLock(); FileLock lock = o.tryLock();
o.truncate(0); o.truncate(0);
o.releaseLock(); if (lock != null) {
lock.release();
}
o.close(); o.close();
} }
...@@ -245,8 +248,10 @@ public class TestFileSystem extends TestBase { ...@@ -245,8 +248,10 @@ public class TestFileSystem extends TestBase {
can = FilePath.get(fsBase).getCanonicalPath().toString(); can = FilePath.get(fsBase).getCanonicalPath().toString();
String can2 = FileUtils.getCanonicalPath(FileUtils.getParent(path)); String can2 = FileUtils.getCanonicalPath(FileUtils.getParent(path));
assertEquals(can, can2); assertEquals(can, can2);
fo.tryLock(); FileLock lock = fo.tryLock();
fo.releaseLock(); if (lock != null) {
lock.release();
}
assertEquals(10000, fo.size()); assertEquals(10000, fo.size());
fo.close(); fo.close();
assertEquals(10000, FileUtils.size(fsBase + "/test")); assertEquals(10000, FileUtils.size(fsBase + "/test"));
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.test.utils; package org.h2.test.utils;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.FileLock;
import org.h2.store.fs.FileObject; import org.h2.store.fs.FileObject;
/** /**
...@@ -83,14 +84,9 @@ public class FileDebug implements FileObject { ...@@ -83,14 +84,9 @@ public class FileDebug implements FileObject {
} }
} }
public boolean tryLock() { public FileLock tryLock() throws IOException {
debug("tryLock"); debug("tryLock");
return file.tryLock(); return file.tryLock();
} }
public void releaseLock() {
debug("releaseLock");
file.releaseLock();
}
} }
\ No newline at end of file
...@@ -8,6 +8,7 @@ package org.h2.dev.fs; ...@@ -8,6 +8,7 @@ package org.h2.dev.fs;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.FileLock;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.security.BlockCipher; import org.h2.security.BlockCipher;
import org.h2.security.CipherFactory; import org.h2.security.CipherFactory;
...@@ -80,10 +81,6 @@ public class FileObjectCrypt implements FileObject { ...@@ -80,10 +81,6 @@ public class FileObjectCrypt implements FileObject {
return Math.max(0, file.size() - HEADER_LENGTH - BLOCK_SIZE); return Math.max(0, file.size() - HEADER_LENGTH - BLOCK_SIZE);
} }
public void releaseLock() {
file.releaseLock();
}
public void position(long pos) throws IOException { public void position(long pos) throws IOException {
file.position(pos + HEADER_LENGTH); file.position(pos + HEADER_LENGTH);
} }
...@@ -92,7 +89,7 @@ public class FileObjectCrypt implements FileObject { ...@@ -92,7 +89,7 @@ public class FileObjectCrypt implements FileObject {
file.sync(); file.sync();
} }
public boolean tryLock() { public FileLock tryLock() throws IOException {
return file.tryLock(); return file.tryLock();
} }
......
...@@ -9,6 +9,7 @@ package org.h2.dev.fs; ...@@ -9,6 +9,7 @@ package org.h2.dev.fs;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.channels.FileLock;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import org.h2.store.fs.FileObject; import org.h2.store.fs.FileObject;
...@@ -109,12 +110,8 @@ public class FileObjectZip2 implements FileObject { ...@@ -109,12 +110,8 @@ public class FileObjectZip2 implements FileObject {
throw new IOException("File is read-only"); throw new IOException("File is read-only");
} }
public boolean tryLock() { public FileLock tryLock() {
return false; return null;
}
public void releaseLock() {
// ignore
} }
public String toString() { public String toString() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论