mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-20 06:54:16 +00:00
Improved error handling
* Created AsyncTaskService to build async UI operations which always log uncaught exceptions * Changed all executor service invocations in the UI to invocations of AsyncTaskService * Improved error handling in some other places, especially try-with-resources * Unlocking read/write locks in NioFile when opening of a channel fails
This commit is contained in:
@@ -30,13 +30,21 @@ class NioFile extends NioNode implements File {
|
||||
@Override
|
||||
public ReadableFile openReadable() throws UncheckedIOException {
|
||||
if (lock.getWriteHoldCount() > 0) {
|
||||
throw new IllegalStateException("Current thread is currently writing this file");
|
||||
throw new IllegalStateException("Current thread is currently writing " + path);
|
||||
}
|
||||
if (lock.getReadHoldCount() > 0) {
|
||||
throw new IllegalStateException("Current thread is already reading this file");
|
||||
throw new IllegalStateException("Current thread is already reading " + path);
|
||||
}
|
||||
lock.readLock().lock();
|
||||
return instanceFactory.readableNioFile(path, sharedChannel, this::unlockReadLock);
|
||||
ReadableFile result = null;
|
||||
try {
|
||||
result = instanceFactory.readableNioFile(path, sharedChannel, this::unlockReadLock);
|
||||
} finally {
|
||||
if (result == null) {
|
||||
unlockReadLock();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void unlockReadLock() {
|
||||
@@ -46,13 +54,21 @@ class NioFile extends NioNode implements File {
|
||||
@Override
|
||||
public WritableFile openWritable() throws UncheckedIOException {
|
||||
if (lock.getWriteHoldCount() > 0) {
|
||||
throw new IllegalStateException("Current thread is already writing this file");
|
||||
throw new IllegalStateException("Current thread is already writing " + path);
|
||||
}
|
||||
if (lock.getReadHoldCount() > 0) {
|
||||
throw new IllegalStateException("Current thread is currently reading this file");
|
||||
throw new IllegalStateException("Current thread is currently reading " + path);
|
||||
}
|
||||
lockWriteLock();
|
||||
return instanceFactory.writableNioFile(fileSystem(), path, sharedChannel, this::unlockWriteLock);
|
||||
WritableFile result = null;
|
||||
try {
|
||||
result = instanceFactory.writableNioFile(fileSystem(), path, sharedChannel, this::unlockWriteLock);
|
||||
} finally {
|
||||
if (result == null) {
|
||||
unlockWriteLock();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
|
||||
@@ -99,10 +99,11 @@ public class NioFileTest {
|
||||
|
||||
@Test
|
||||
public void testOpenReadableInvokedBeforeInvokingAfterCloseOperationThrowsIllegalStateException() {
|
||||
when(instanceFactory.readableNioFile(same(path), same(channel), any())).thenReturn(mock(ReadableNioFile.class));
|
||||
inTest.openReadable();
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("already reading this file");
|
||||
thrown.expectMessage("already reading " + path);
|
||||
|
||||
inTest.openReadable();
|
||||
}
|
||||
@@ -111,7 +112,7 @@ public class NioFileTest {
|
||||
public void testOpenReadableInvokedAfterAfterCloseOperationCreatesNewReadableFile() {
|
||||
ReadableNioFile readableNioFile = mock(ReadableNioFile.class);
|
||||
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
|
||||
when(instanceFactory.readableNioFile(same(path), same(channel), captor.capture())).thenReturn(null, readableNioFile);
|
||||
when(instanceFactory.readableNioFile(same(path), same(channel), captor.capture())).thenReturn(mock(ReadableNioFile.class), readableNioFile);
|
||||
inTest.openReadable();
|
||||
captor.getValue().run();
|
||||
|
||||
@@ -122,10 +123,11 @@ public class NioFileTest {
|
||||
|
||||
@Test
|
||||
public void testOpenReadableInvokedBeforeInvokingAfterCloseOperationOfOpenWritableThrowsIllegalStateException() {
|
||||
when(instanceFactory.writableNioFile(same(fileSystem), same(path), same(channel), any())).thenReturn(mock(WritableNioFile.class));
|
||||
inTest.openWritable();
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("currently writing this file");
|
||||
thrown.expectMessage("currently writing " + path);
|
||||
|
||||
inTest.openReadable();
|
||||
}
|
||||
@@ -133,7 +135,7 @@ public class NioFileTest {
|
||||
@Test
|
||||
public void testOpenReadableInvokedAfterInvokingAfterCloseOperationWorks() {
|
||||
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
|
||||
when(instanceFactory.writableNioFile(same(fileSystem), same(path), same(channel), captor.capture())).thenReturn(null);
|
||||
when(instanceFactory.writableNioFile(same(fileSystem), same(path), same(channel), captor.capture())).thenReturn(mock(WritableNioFile.class));
|
||||
inTest.openWritable();
|
||||
captor.getValue().run();
|
||||
|
||||
@@ -154,7 +156,7 @@ public class NioFileTest {
|
||||
public void testOpenWritableInvokedAfterAfterCloseOperationCreatesNewWritableFile() {
|
||||
WritableNioFile writableNioFile = mock(WritableNioFile.class);
|
||||
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
|
||||
when(instanceFactory.writableNioFile(same(fileSystem), same(path), same(channel), captor.capture())).thenReturn(null, writableNioFile);
|
||||
when(instanceFactory.writableNioFile(same(fileSystem), same(path), same(channel), captor.capture())).thenReturn(mock(WritableNioFile.class), writableNioFile);
|
||||
inTest.openWritable();
|
||||
captor.getValue().run();
|
||||
|
||||
@@ -165,28 +167,31 @@ public class NioFileTest {
|
||||
|
||||
@Test
|
||||
public void testOpenWritableInvokedBeforeInvokingAfterCloseOperationThrowsIllegalStateException() {
|
||||
when(instanceFactory.writableNioFile(same(fileSystem), same(path), same(channel), any())).thenReturn(mock(WritableNioFile.class));
|
||||
inTest.openWritable();
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("already writing this file");
|
||||
thrown.expectMessage("already writing " + path);
|
||||
|
||||
inTest.openWritable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenWritableInvokedBeforeInvokingAfterCloseOperationFromOpenReadableThrowsIllegalStateException() {
|
||||
when(instanceFactory.readableNioFile(same(path), same(channel), any())).thenReturn(mock(ReadableNioFile.class));
|
||||
inTest.openReadable();
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("currently reading this file");
|
||||
thrown.expectMessage("currently reading " + path);
|
||||
|
||||
inTest.openWritable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenWritableInvokedAfterInvokingAfterCloseOperationWorks() {
|
||||
ReadableNioFile readableNioFile = mock(ReadableNioFile.class);
|
||||
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
|
||||
when(instanceFactory.readableNioFile(same(path), same(channel), captor.capture())).thenReturn(null);
|
||||
when(instanceFactory.readableNioFile(same(path), same(channel), captor.capture())).thenReturn(readableNioFile);
|
||||
inTest.openReadable();
|
||||
captor.getValue().run();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user