Changes to filesystem API and nio implementation

* Partial implementation of nio filesystem
* Removed timeouts from openReadable and openWritable
* Added convenience methods for copying
* Added utility to support deadlock safe opening of multiple files
This commit is contained in:
Markus Kreusch
2015-12-17 23:46:58 +01:00
parent 58524e5099
commit 25eed3dc4a
29 changed files with 725 additions and 165 deletions
@@ -12,14 +12,13 @@ import java.io.FileNotFoundException;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.cryptomator.filesystem.File;
import org.cryptomator.filesystem.ReadableFile;
import org.cryptomator.filesystem.WritableFile;
class InMemoryFile extends InMemoryNode implements ReadableFile, WritableFile {
class InMemoryFile extends InMemoryNode implements File, ReadableFile, WritableFile {
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private ByteBuffer content = ByteBuffer.wrap(new byte[0]);
@@ -29,29 +28,17 @@ class InMemoryFile extends InMemoryNode implements ReadableFile, WritableFile {
}
@Override
public ReadableFile openReadable(long timeout, TimeUnit unit) throws TimeoutException {
public ReadableFile openReadable() {
if (!exists()) {
throw new UncheckedIOException(new FileNotFoundException(this.name() + " does not exist"));
}
try {
if (!lock.readLock().tryLock(timeout, unit)) {
throw new TimeoutException("Failed to open " + name() + " for reading within time limit.");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
lock.readLock().lock();
return this;
}
@Override
public WritableFile openWritable(long timeout, TimeUnit unit) throws TimeoutException {
try {
if (!lock.writeLock().tryLock(timeout, unit)) {
throw new TimeoutException("Failed to open " + name() + " for writing within time limit.");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
public WritableFile openWritable() {
lock.writeLock().lock();
final InMemoryFolder parent = parent().get();
parent.children.compute(this.name(), (k, v) -> {
if (v != null && v != this) {
@@ -123,7 +110,7 @@ class InMemoryFile extends InMemoryNode implements ReadableFile, WritableFile {
// returning null removes the entry.
return null;
});
assert!this.exists();
assert !this.exists();
}
@Override
@@ -141,4 +128,9 @@ class InMemoryFile extends InMemoryNode implements ReadableFile, WritableFile {
return parent.toString() + name;
}
@Override
public int compareTo(File o) {
return toString().compareTo(o.toString());
}
}
@@ -64,7 +64,7 @@ public class InMemoryFileSystemTest {
Thread.sleep(1);
// write "hello world" to foo
try (WritableFile writable = fooFile.openWritable(1, TimeUnit.SECONDS)) {
try (WritableFile writable = fooFile.openWritable()) {
writable.write(ByteBuffer.wrap("hello world".getBytes()));
}
Assert.assertTrue(fooFile.exists());
@@ -79,7 +79,7 @@ public class InMemoryFileSystemTest {
Thread.sleep(1);
// write "dlrow olleh" to foo
try (WritableFile writable = fooFile.openWritable(1, TimeUnit.SECONDS)) {
try (WritableFile writable = fooFile.openWritable()) {
writable.write(ByteBuffer.wrap("dlrow olleh".getBytes()));
}
Assert.assertTrue(fooFile.exists());
@@ -98,7 +98,7 @@ public class InMemoryFileSystemTest {
Assert.assertEquals(0, fs.files().count());
// write "hello world" to foo
try (WritableFile writable = fooFile.openWritable(1, TimeUnit.SECONDS)) {
try (WritableFile writable = fooFile.openWritable()) {
writable.write(ByteBuffer.wrap("hello".getBytes()));
writable.write(ByteBuffer.wrap(" ".getBytes()));
writable.write(ByteBuffer.wrap("world".getBytes()));
@@ -107,8 +107,8 @@ public class InMemoryFileSystemTest {
// copy foo to bar
File barFile = fs.file("bar.txt");
try (WritableFile writable = barFile.openWritable(1, TimeUnit.SECONDS)) {
try (ReadableFile readable = fooFile.openReadable(1, TimeUnit.SECONDS)) {
try (WritableFile writable = barFile.openWritable()) {
try (ReadableFile readable = fooFile.openReadable()) {
readable.copyTo(writable);
}
}
@@ -117,8 +117,8 @@ public class InMemoryFileSystemTest {
// move bar to baz
File bazFile = fs.file("baz.txt");
try (WritableFile src = barFile.openWritable(1, TimeUnit.SECONDS)) {
try (WritableFile dst = bazFile.openWritable(1, TimeUnit.SECONDS)) {
try (WritableFile src = barFile.openWritable()) {
try (WritableFile dst = bazFile.openWritable()) {
src.moveTo(dst);
}
}
@@ -127,7 +127,7 @@ public class InMemoryFileSystemTest {
// read "hello world" from baz
final ByteBuffer readBuf = ByteBuffer.allocate(5);
try (ReadableFile readable = bazFile.openReadable(1, TimeUnit.SECONDS)) {
try (ReadableFile readable = bazFile.openReadable()) {
readable.read(readBuf, 6);
}
Assert.assertEquals("world", new String(readBuf.array()));
@@ -143,8 +143,8 @@ public class InMemoryFileSystemTest {
fooBarFolder.create(FolderCreateMode.INCLUDING_PARENTS);
// create some files inside foo/bar/
try (WritableFile writable1 = test1File.openWritable(1, TimeUnit.SECONDS); //
WritableFile writable2 = test2File.openWritable(1, TimeUnit.SECONDS)) {
try (WritableFile writable1 = test1File.openWritable(); //
WritableFile writable2 = test2File.openWritable()) {
writable1.write(ByteBuffer.wrap("hello".getBytes()));
writable2.write(ByteBuffer.wrap("world".getBytes()));
}