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

Improved compatibility with the Java 7 FileSystem abstraction.

上级 abc9cec3
......@@ -54,6 +54,7 @@ public class FileStore {
private String mode;
private TempFileDeleter tempFileDeleter;
private boolean textMode;
private java.nio.channels.FileLock lock;
/**
* Create a new file using the given settings.
......@@ -492,16 +493,27 @@ public class FileStore {
*
* @return true if successful
*/
public boolean tryLock() {
return file.tryLock();
public synchronized boolean tryLock() {
try {
lock = file.tryLock();
return true;
} catch (IOException e) {
// ignore
return false;
}
}
/**
* Release the file lock.
*/
public void releaseLock() {
if (file != null) {
file.releaseLock();
public synchronized void releaseLock() {
if (file != null && lock != null) {
try {
lock.release();
} catch (IOException e) {
// ignore
}
lock = null;
}
}
......
......@@ -7,6 +7,7 @@
package org.h2.store.fs;
import java.io.IOException;
import java.nio.channels.FileLock;
/**
* This interface represents a random access file.
......@@ -71,13 +72,8 @@ public interface FileObject {
/**
* Try to lock the file exclusively.
*
* @return true if locking was successful
* @return a lock object if successful, or null if not
*/
boolean tryLock();
/**
* Release the file lock.
*/
void releaseLock();
FileLock tryLock() throws IOException;
}
......@@ -19,7 +19,6 @@ public class FileObjectDisk implements FileObject {
private final RandomAccessFile file;
private final String name;
private FileLock lock;
FileObjectDisk(String fileName, String mode) throws FileNotFoundException {
this.file = new RandomAccessFile(fileName, mode);
......@@ -48,27 +47,8 @@ public class FileObjectDisk implements FileObject {
}
}
public synchronized boolean tryLock() {
if (lock == null) {
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 synchronized FileLock tryLock() throws IOException {
return file.getChannel().tryLock();
}
public void close() throws IOException {
......
......@@ -7,6 +7,7 @@
package org.h2.store.fs;
import java.io.IOException;
import java.nio.channels.FileLock;
/**
* This class represents an in-memory file.
......@@ -60,12 +61,8 @@ public class FileObjectMem implements FileObject {
// do nothing
}
public boolean tryLock() {
return data.tryLock();
}
public void releaseLock() {
data.releaseLock();
public FileLock tryLock() {
return null;
}
}
......@@ -22,7 +22,6 @@ public class FileObjectNio implements FileObject {
private final String name;
private final RandomAccessFile file;
private final FileChannel channel;
private FileLock lock;
private long length;
FileObjectNio(String fileName, String mode) throws IOException {
......@@ -94,27 +93,8 @@ public class FileObjectNio implements FileObject {
}
}
public synchronized boolean tryLock() {
if (lock == null) {
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 synchronized FileLock tryLock() throws IOException {
return channel.tryLock();
}
public String toString() {
......
......@@ -28,7 +28,6 @@ public class FileObjectNioMapped implements FileObject {
private final MapMode mode;
private RandomAccessFile file;
private MappedByteBuffer mapped;
private FileLock lock;
/**
* The position within the file. Can't use the position of the mapped buffer
......@@ -202,27 +201,8 @@ public class FileObjectNioMapped implements FileObject {
pos += len;
}
public synchronized boolean tryLock() {
if (lock == null) {
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;
}
public synchronized FileLock tryLock() throws IOException {
return file.getChannel().tryLock();
}
}
......@@ -7,6 +7,7 @@
package org.h2.store.fs;
import java.io.IOException;
import java.nio.channels.FileLock;
/**
* A file object that records all write operations and can re-play them.
......@@ -62,12 +63,8 @@ public class FileObjectRec implements FileObject {
fs.log(Recorder.WRITE, name, buff, file.position());
}
public boolean tryLock() {
public FileLock tryLock() throws IOException {
return file.tryLock();
}
public void releaseLock() {
file.releaseLock();
}
}
\ No newline at end of file
......@@ -8,6 +8,7 @@ package org.h2.store.fs;
import java.io.EOFException;
import java.io.IOException;
import java.nio.channels.FileLock;
import org.h2.message.DbException;
/**
......@@ -153,12 +154,8 @@ public class FileObjectSplit implements FileObject {
return l;
}
public boolean tryLock() {
public FileLock tryLock() throws IOException {
return list[0].tryLock();
}
public void releaseLock() {
list[0].releaseLock();
}
}
......@@ -9,6 +9,7 @@ package org.h2.store.fs;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileLock;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
......@@ -103,12 +104,8 @@ public class FileObjectZip implements FileObject {
throw new IOException("File is read-only");
}
public boolean tryLock() {
return false;
}
public void releaseLock() {
// ignore
public FileLock tryLock() {
return null;
}
}
......@@ -29,7 +29,7 @@ public abstract class FilePath {
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 long tempSequence;
......
......@@ -15,7 +15,7 @@ import java.io.IOException;
public class FilePathNio extends FilePathWrapper {
public FileObject openFileObject(String mode) throws IOException {
return new FileObjectNio(name, mode);
return new FileObjectNio(name.substring(getScheme().length() + 1), mode);
}
public String getScheme() {
......
......@@ -15,7 +15,7 @@ import java.io.IOException;
public class FilePathNioMapped extends FilePathNio {
public FileObject openFileObject(String mode) throws IOException {
return new FileObjectNioMapped(name, mode);
return new FileObjectNioMapped(name.substring(getScheme().length() + 1), mode);
}
public String getScheme() {
......
......@@ -324,322 +324,4 @@ public class FileUtils {
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;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
......@@ -112,9 +113,11 @@ public class TestFileSystem extends TestBase {
FileObject o = FileUtils.openFileObject(f, "rw");
o.position(4000);
o.write(new byte[1], 0, 1);
o.tryLock();
FileLock lock = o.tryLock();
o.truncate(0);
o.releaseLock();
if (lock != null) {
lock.release();
}
o.close();
}
......@@ -245,8 +248,10 @@ public class TestFileSystem extends TestBase {
can = FilePath.get(fsBase).getCanonicalPath().toString();
String can2 = FileUtils.getCanonicalPath(FileUtils.getParent(path));
assertEquals(can, can2);
fo.tryLock();
fo.releaseLock();
FileLock lock = fo.tryLock();
if (lock != null) {
lock.release();
}
assertEquals(10000, fo.size());
fo.close();
assertEquals(10000, FileUtils.size(fsBase + "/test"));
......
......@@ -7,6 +7,7 @@
package org.h2.test.utils;
import java.io.IOException;
import java.nio.channels.FileLock;
import org.h2.store.fs.FileObject;
/**
......@@ -83,14 +84,9 @@ public class FileDebug implements FileObject {
}
}
public boolean tryLock() {
public FileLock tryLock() throws IOException {
debug("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;
import java.io.EOFException;
import java.io.IOException;
import java.nio.channels.FileLock;
import org.h2.engine.Constants;
import org.h2.security.BlockCipher;
import org.h2.security.CipherFactory;
......@@ -80,10 +81,6 @@ public class FileObjectCrypt implements FileObject {
return Math.max(0, file.size() - HEADER_LENGTH - BLOCK_SIZE);
}
public void releaseLock() {
file.releaseLock();
}
public void position(long pos) throws IOException {
file.position(pos + HEADER_LENGTH);
}
......@@ -92,7 +89,7 @@ public class FileObjectCrypt implements FileObject {
file.sync();
}
public boolean tryLock() {
public FileLock tryLock() throws IOException {
return file.tryLock();
}
......
......@@ -9,6 +9,7 @@ package org.h2.dev.fs;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileLock;
import java.util.zip.ZipInputStream;
import org.h2.store.fs.FileObject;
......@@ -109,12 +110,8 @@ public class FileObjectZip2 implements FileObject {
throw new IOException("File is read-only");
}
public boolean tryLock() {
return false;
}
public void releaseLock() {
// ignore
public FileLock tryLock() {
return null;
}
public String toString() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论