Skip to content

Commit fd2119a

Browse files
BoxStore: throw if not open on subscribe, clean (#818)
- Also test various methods when closed. - Use existing check open check for getNativeStore().
1 parent 063e75f commit fd2119a

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

objectbox-java/src/main/java/io/objectbox/BoxStore.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,7 @@ public long validate(long pageLimit, boolean checkLeafLevel) {
10671067
}
10681068

10691069
public int cleanStaleReadTransactions() {
1070+
checkOpen();
10701071
return nativeCleanStaleReadTransactions(handle);
10711072
}
10721073

@@ -1100,6 +1101,7 @@ long internalHandle() {
11001101
* Note that failed or aborted transaction do not trigger observers.
11011102
*/
11021103
public SubscriptionBuilder<Class> subscribe() {
1104+
checkOpen();
11031105
return new SubscriptionBuilder<>(objectClassPublisher, null);
11041106
}
11051107

@@ -1109,6 +1111,7 @@ public SubscriptionBuilder<Class> subscribe() {
11091111
*/
11101112
@SuppressWarnings("unchecked")
11111113
public <T> SubscriptionBuilder<Class<T>> subscribe(Class<T> forClass) {
1114+
checkOpen();
11121115
return new SubscriptionBuilder<>((DataPublisher) objectClassPublisher, forClass);
11131116
}
11141117

@@ -1246,9 +1249,7 @@ long panicModeRemoveAllObjects(int entityId) {
12461249
* Note: Once you {@link #close()} this BoxStore, do not use it from the C API.
12471250
*/
12481251
public long getNativeStore() {
1249-
if (closed) {
1250-
throw new IllegalStateException("Store must still be open");
1251-
}
1252+
checkOpen();
12521253
return handle;
12531254
}
12541255

tests/objectbox-java-test/src/test/java/io/objectbox/BoxStoreTest.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818

1919
import io.objectbox.exception.DbException;
2020
import org.junit.Test;
21+
import org.junit.function.ThrowingRunnable;
2122

2223
import java.io.File;
2324
import java.util.concurrent.Callable;
25+
import java.util.concurrent.RejectedExecutionException;
2426

2527
import static org.junit.Assert.assertEquals;
2628
import static org.junit.Assert.assertFalse;
2729
import static org.junit.Assert.assertNotNull;
2830
import static org.junit.Assert.assertNotSame;
2931
import static org.junit.Assert.assertSame;
32+
import static org.junit.Assert.assertThrows;
3033
import static org.junit.Assert.assertTrue;
3134
import static org.junit.Assert.fail;
3235

@@ -39,12 +42,72 @@ public void testUnalignedMemoryAccess() {
3942

4043
@Test
4144
public void testClose() {
45+
BoxStore store = this.store;
4246
assertFalse(store.isClosed());
4347
store.close();
4448
assertTrue(store.isClosed());
4549

4650
// Double close should be fine
4751
store.close();
52+
53+
// Internal thread pool is shut down.
54+
assertTrue(store.internalThreadPool().isShutdown());
55+
assertTrue(store.internalThreadPool().isTerminated());
56+
57+
// Can still obtain a box (but not use it).
58+
store.boxFor(TestEntity.class);
59+
store.closeThreadResources();
60+
//noinspection ResultOfMethodCallIgnored
61+
store.getObjectBrowserPort();
62+
store.isObjectBrowserRunning();
63+
//noinspection ResultOfMethodCallIgnored
64+
store.isDebugRelations();
65+
store.internalQueryAttempts();
66+
store.internalFailedReadTxAttemptCallback();
67+
//noinspection ResultOfMethodCallIgnored
68+
store.getSyncClient();
69+
store.setSyncClient(null);
70+
71+
// Methods using the native store should throw.
72+
assertThrowsStoreIsClosed(store::sizeOnDisk);
73+
assertThrowsStoreIsClosed(store::beginTx);
74+
assertThrowsStoreIsClosed(store::beginReadTx);
75+
assertThrowsStoreIsClosed(store::isReadOnly);
76+
assertThrowsStoreIsClosed(store::removeAllObjects);
77+
assertThrowsStoreIsClosed(() -> store.runInTx(() -> {
78+
}));
79+
assertThrowsStoreIsClosed(() -> store.runInReadTx(() -> {
80+
}));
81+
assertThrowsStoreIsClosed(() -> store.callInReadTxWithRetry(() -> null,
82+
3, 1, true));
83+
assertThrowsStoreIsClosed(() -> store.callInReadTx(() -> null));
84+
assertThrowsStoreIsClosed(() -> store.callInTx(() -> null));
85+
// callInTxNoException wraps in RuntimeException
86+
RuntimeException runtimeException = assertThrows(RuntimeException.class, () -> store.callInTxNoException(() -> null));
87+
assertEquals("java.lang.IllegalStateException: Store is closed", runtimeException.getMessage());
88+
// Internal thread pool is shut down as part of closing store, should no longer accept new work.
89+
assertThrows(RejectedExecutionException.class, () -> store.runInTxAsync(() -> {}, null));
90+
assertThrows(RejectedExecutionException.class, () -> store.callInTxAsync(() -> null, null));
91+
assertThrowsStoreIsClosed(store::diagnose);
92+
assertThrowsStoreIsClosed(() -> store.validate(0, false));
93+
assertThrowsStoreIsClosed(store::cleanStaleReadTransactions);
94+
assertThrowsStoreIsClosed(store::subscribe);
95+
assertThrowsStoreIsClosed(() -> store.subscribe(TestEntity.class));
96+
assertThrowsStoreIsClosed(store::startObjectBrowser);
97+
assertThrowsStoreIsClosed(() -> store.startObjectBrowser(12345));
98+
assertThrowsStoreIsClosed(() -> store.startObjectBrowser(""));
99+
// assertThrowsStoreIsClosed(store::stopObjectBrowser); // Requires mocking, not testing for now.
100+
assertThrowsStoreIsClosed(() -> store.setDbExceptionListener(null));
101+
// Internal thread pool is shut down as part of closing store, should no longer accept new work.
102+
assertThrows(RejectedExecutionException.class, () -> store.internalScheduleThread(() -> {}));
103+
assertThrowsStoreIsClosed(() -> store.setDebugFlags(0));
104+
assertThrowsStoreIsClosed(() -> store.panicModeRemoveAllObjects(TestEntity_.__ENTITY_ID));
105+
assertThrowsStoreIsClosed(store::getNativeStore);
106+
}
107+
108+
private void assertThrowsStoreIsClosed(ThrowingRunnable runnable) {
109+
IllegalStateException ex = assertThrows(IllegalStateException.class, runnable);
110+
assertEquals("Store is closed", ex.getMessage());
48111
}
49112

50113
@Test

0 commit comments

Comments
 (0)