Skip to content

Commit 789e99a

Browse files
BoxStore: route all native handle access through method with open check.
1 parent 1e9c96a commit 789e99a

File tree

7 files changed

+39
-49
lines changed

7 files changed

+39
-49
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ public long panicModeRemoveAll() {
574574
* Returns a builder to create queries for Object matching supplied criteria.
575575
*/
576576
public QueryBuilder<T> query() {
577-
return new QueryBuilder<>(this, store.internalHandle(), store.getDbName(entityClass));
577+
return new QueryBuilder<>(this, store.getNativeStore(), store.getDbName(entityClass));
578578
}
579579

580580
/**

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

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ public static boolean isSyncServerAvailable() {
220220

221221
private final File directory;
222222
private final String canonicalPath;
223+
/** Reference to the native store. Should probably get through {@link #getNativeStore()} instead. */
223224
private final long handle;
224225
private final Map<Class<?>, String> dbNameByClass = new HashMap<>();
225226
private final Map<Class<?>, Integer> entityTypeIdByClass = new HashMap<>();
@@ -467,11 +468,12 @@ public static long sysProcStatusKb(String key) {
467468
* @return 0 if the size could not be determined (does not throw unless this store was already closed)
468469
*/
469470
public long sizeOnDisk() {
470-
checkOpen();
471-
return nativeSizeOnDisk(handle);
471+
return nativeSizeOnDisk(getNativeStore());
472472
}
473473

474474
/**
475+
* Closes this if this is finalized.
476+
* <p>
475477
* Explicitly call {@link #close()} instead to avoid expensive finalization.
476478
*/
477479
@SuppressWarnings("deprecation") // finalize()
@@ -481,8 +483,11 @@ protected void finalize() throws Throwable {
481483
super.finalize();
482484
}
483485

486+
/**
487+
* Verifies this has not been {@link #close() closed}.
488+
*/
484489
private void checkOpen() {
485-
if (closed) {
490+
if (isClosed()) {
486491
throw new IllegalStateException("Store is closed");
487492
}
488493
}
@@ -533,13 +538,12 @@ <T> EntityInfo<T> getEntityInfo(Class<T> entityClass) {
533538
*/
534539
@Internal
535540
public Transaction beginTx() {
536-
checkOpen();
537541
// Because write TXs are typically not cached, initialCommitCount is not as relevant than for read TXs.
538542
int initialCommitCount = commitCount;
539543
if (debugTxWrite) {
540544
System.out.println("Begin TX with commit count " + initialCommitCount);
541545
}
542-
long nativeTx = nativeBeginTx(handle);
546+
long nativeTx = nativeBeginTx(getNativeStore());
543547
if (nativeTx == 0) throw new DbException("Could not create native transaction");
544548

545549
Transaction tx = new Transaction(this, nativeTx, initialCommitCount);
@@ -555,7 +559,6 @@ public Transaction beginTx() {
555559
*/
556560
@Internal
557561
public Transaction beginReadTx() {
558-
checkOpen();
559562
// initialCommitCount should be acquired before starting the tx. In race conditions, there is a chance the
560563
// commitCount is already outdated. That's OK because it only gives a false positive for an TX being obsolete.
561564
// In contrast, a false negative would make a TX falsely not considered obsolete, and thus readers would not be
@@ -565,7 +568,7 @@ public Transaction beginReadTx() {
565568
if (debugTxRead) {
566569
System.out.println("Begin read TX with commit count " + initialCommitCount);
567570
}
568-
long nativeTx = nativeBeginReadTx(handle);
571+
long nativeTx = nativeBeginReadTx(getNativeStore());
569572
if (nativeTx == 0) throw new DbException("Could not create native read transaction");
570573

571574
Transaction tx = new Transaction(this, nativeTx, initialCommitCount);
@@ -575,6 +578,9 @@ public Transaction beginReadTx() {
575578
return tx;
576579
}
577580

581+
/**
582+
* If this was {@link #close() closed}.
583+
*/
578584
public boolean isClosed() {
579585
return closed;
580586
}
@@ -584,8 +590,7 @@ public boolean isClosed() {
584590
* If true the schema is not updated and write transactions are not possible.
585591
*/
586592
public boolean isReadOnly() {
587-
checkOpen();
588-
return nativeIsReadOnly(handle);
593+
return nativeIsReadOnly(getNativeStore());
589594
}
590595

591596
/**
@@ -665,7 +670,7 @@ private void checkThreadTermination() {
665670
* Note: If false is returned, any number of files may have been deleted before the failure happened.
666671
*/
667672
public boolean deleteAllFiles() {
668-
if (!closed) {
673+
if (!isClosed()) {
669674
throw new IllegalStateException("Store must be closed");
670675
}
671676
return deleteAllFiles(directory);
@@ -765,8 +770,7 @@ public static boolean deleteAllFiles(@Nullable File baseDirectoryOrNull, @Nullab
765770
* </ul>
766771
*/
767772
public void removeAllObjects() {
768-
checkOpen();
769-
nativeDropAllData(handle);
773+
nativeDropAllData(getNativeStore());
770774
}
771775

772776
@Internal
@@ -1049,8 +1053,7 @@ public <R> void callInTxAsync(final Callable<R> callable, @Nullable final TxCall
10491053
* @return String that is typically logged by the application.
10501054
*/
10511055
public String diagnose() {
1052-
checkOpen();
1053-
return nativeDiagnose(handle);
1056+
return nativeDiagnose(getNativeStore());
10541057
}
10551058

10561059
/**
@@ -1069,13 +1072,11 @@ public long validate(long pageLimit, boolean checkLeafLevel) {
10691072
if (pageLimit < 0) {
10701073
throw new IllegalArgumentException("pageLimit must be zero or positive");
10711074
}
1072-
checkOpen();
1073-
return nativeValidate(handle, pageLimit, checkLeafLevel);
1075+
return nativeValidate(getNativeStore(), pageLimit, checkLeafLevel);
10741076
}
10751077

10761078
public int cleanStaleReadTransactions() {
1077-
checkOpen();
1078-
return nativeCleanStaleReadTransactions(handle);
1079+
return nativeCleanStaleReadTransactions(getNativeStore());
10791080
}
10801081

10811082
/**
@@ -1090,11 +1091,6 @@ public void closeThreadResources() {
10901091
// activeTx is cleaned up in finally blocks, so do not free them here
10911092
}
10921093

1093-
@Internal
1094-
long internalHandle() {
1095-
return handle;
1096-
}
1097-
10981094
/**
10991095
* A {@link io.objectbox.reactive.DataObserver} can be subscribed to data changes using the returned builder.
11001096
* The observer is supplied via {@link SubscriptionBuilder#observer(DataObserver)} and will be notified once a
@@ -1146,8 +1142,7 @@ public String startObjectBrowser() {
11461142
@Nullable
11471143
public String startObjectBrowser(int port) {
11481144
verifyObjectBrowserNotRunning();
1149-
checkOpen();
1150-
String url = nativeStartObjectBrowser(handle, null, port);
1145+
String url = nativeStartObjectBrowser(getNativeStore(), null, port);
11511146
if (url != null) {
11521147
objectBrowserPort = port;
11531148
}
@@ -1158,14 +1153,13 @@ public String startObjectBrowser(int port) {
11581153
@Nullable
11591154
public String startObjectBrowser(String urlToBindTo) {
11601155
verifyObjectBrowserNotRunning();
1161-
checkOpen();
11621156
int port;
11631157
try {
11641158
port = new URL(urlToBindTo).getPort(); // Gives -1 if not available
11651159
} catch (MalformedURLException e) {
11661160
throw new RuntimeException("Can not start Object Browser at " + urlToBindTo, e);
11671161
}
1168-
String url = nativeStartObjectBrowser(handle, urlToBindTo, 0);
1162+
String url = nativeStartObjectBrowser(getNativeStore(), urlToBindTo, 0);
11691163
if (url != null) {
11701164
objectBrowserPort = port;
11711165
}
@@ -1178,8 +1172,7 @@ public synchronized boolean stopObjectBrowser() {
11781172
throw new IllegalStateException("ObjectBrowser has not been started before");
11791173
}
11801174
objectBrowserPort = 0;
1181-
checkOpen();
1182-
return nativeStopObjectBrowser(handle);
1175+
return nativeStopObjectBrowser(getNativeStore());
11831176
}
11841177

11851178
@Experimental
@@ -1204,8 +1197,7 @@ private void verifyObjectBrowserNotRunning() {
12041197
* This for example allows central error handling or special logging for database-related exceptions.
12051198
*/
12061199
public void setDbExceptionListener(@Nullable DbExceptionListener dbExceptionListener) {
1207-
checkOpen();
1208-
nativeSetDbExceptionListener(handle, dbExceptionListener);
1200+
nativeSetDbExceptionListener(getNativeStore(), dbExceptionListener);
12091201
}
12101202

12111203
@Internal
@@ -1234,18 +1226,19 @@ public TxCallback<?> internalFailedReadTxAttemptCallback() {
12341226
}
12351227

12361228
void setDebugFlags(int debugFlags) {
1237-
checkOpen();
1238-
nativeSetDebugFlags(handle, debugFlags);
1229+
nativeSetDebugFlags(getNativeStore(), debugFlags);
12391230
}
12401231

12411232
long panicModeRemoveAllObjects(int entityId) {
1242-
checkOpen();
1243-
return nativePanicModeRemoveAllObjects(handle, entityId);
1233+
return nativePanicModeRemoveAllObjects(getNativeStore(), entityId);
12441234
}
12451235

12461236
/**
1247-
* If you want to use the same ObjectBox store using the C API, e.g. via JNI, this gives the required pointer,
1248-
* which you have to pass on to obx_store_wrap().
1237+
* Gets the reference to the native store. Can be used with the C API to use the same store, e.g. via JNI, by
1238+
* passing it on to {@code obx_store_wrap()}.
1239+
* <p>
1240+
* Throws if the store is closed.
1241+
* <p>
12491242
* The procedure is like this:<br>
12501243
* 1) you create a BoxStore on the Java side<br>
12511244
* 2) you call this method to get the native store pointer<br>

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@
2424
@Internal
2525
public class InternalAccess {
2626

27-
public static long getHandle(BoxStore boxStore) {
28-
return boxStore.internalHandle();
29-
}
30-
3127
public static Transaction getActiveTx(BoxStore boxStore) {
3228
Transaction tx = boxStore.activeTx.get();
3329
if (tx == null) {

objectbox-java/src/main/java/io/objectbox/sync/SyncClientImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class SyncClientImpl implements SyncClient {
4848
this.serverUrl = builder.url;
4949
this.connectivityMonitor = builder.platform.getConnectivityMonitor();
5050

51-
long boxStoreHandle = InternalAccess.getHandle(builder.boxStore);
51+
long boxStoreHandle = builder.boxStore.getNativeStore();
5252
long handle = nativeCreate(boxStoreHandle, serverUrl, builder.trustedCertPaths);
5353
if (handle == 0) {
5454
throw new RuntimeException("Failed to create sync client: handle is zero.");

objectbox-java/src/main/java/io/objectbox/sync/server/SyncServerImpl.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import javax.annotation.Nullable;
44

5-
import io.objectbox.InternalAccess;
65
import io.objectbox.annotation.apihint.Internal;
76
import io.objectbox.sync.SyncCredentials;
87
import io.objectbox.sync.SyncCredentialsToken;
@@ -24,7 +23,7 @@ public class SyncServerImpl implements SyncServer {
2423
SyncServerImpl(SyncServerBuilder builder) {
2524
this.url = builder.url;
2625

27-
long storeHandle = InternalAccess.getHandle(builder.boxStore);
26+
long storeHandle = builder.boxStore.getNativeStore();
2827
long handle = nativeCreate(storeHandle, url, builder.certificatePath);
2928
if (handle == 0) {
3029
throw new RuntimeException("Failed to create sync server: handle is zero.");

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public void testClose() {
136136
assertThrowsStoreIsClosed(() -> store.subscribe(TestEntity.class));
137137
assertThrowsStoreIsClosed(store::startObjectBrowser);
138138
assertThrowsStoreIsClosed(() -> store.startObjectBrowser(12345));
139-
assertThrowsStoreIsClosed(() -> store.startObjectBrowser(""));
139+
assertThrowsStoreIsClosed(() -> store.startObjectBrowser("http://127.0.0.1"));
140140
// assertThrowsStoreIsClosed(store::stopObjectBrowser); // Requires mocking, not testing for now.
141141
assertThrowsStoreIsClosed(() -> store.setDbExceptionListener(null));
142142
// Internal thread pool is shut down as part of closing store, should no longer accept new work.

tests/objectbox-java-test/src/test/java/io/objectbox/query/QueryTest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,11 @@ public class QueryTest extends AbstractQueryTest {
6262
public void createIfStoreClosed_throws() {
6363
store.close();
6464

65-
IllegalStateException ex = assertThrows(IllegalStateException.class, () -> box.query());
66-
// FIXME Replace with actual error message
67-
assertEquals("No schema set on store", ex.getMessage());
65+
IllegalStateException ex = assertThrows(
66+
IllegalStateException.class,
67+
() -> box.query()
68+
);
69+
assertEquals("Store is closed", ex.getMessage());
6870
}
6971

7072
@Test

0 commit comments

Comments
 (0)