/** * Like {@link #runInTx(Runnable)}, but allows returning a value and throwing an exception. */ public <R> R callInTx(Callable<R> callable) throws Exception { Transaction tx = activeTx.get(); // Only if not already set, allowing to call it recursively with first (outer) TX if (tx == null) { tx = beginTx(); activeTx.set(tx); try { R result = callable.call(); tx.commit(); return result; } finally { activeTx.remove(); tx.close(); } } else { if (tx.isReadOnly()) { throw new IllegalStateException("Cannot start a transaction while a read only transaction is active"); } return callable.call(); } }
void releaseReader(Cursor<T> cursor) { // NOP if TX is ongoing if (activeTxCursor.get() == null) { Transaction tx = cursor.getTx(); if (tx.isClosed() || tx.isRecycled() || !tx.isReadOnly()) { throw new IllegalStateException("Illegal reader TX state"); } tx.recycle(); } }
/** * Runs the given runnable inside a transaction. * <p> * Efficiency notes: it is advised to run multiple puts in a transaction because each commit requires an expensive * disk synchronization. */ public void runInTx(Runnable runnable) { Transaction tx = activeTx.get(); // Only if not already set, allowing to call it recursively with first (outer) TX if (tx == null) { tx = beginTx(); activeTx.set(tx); try { runnable.run(); tx.commit(); } finally { activeTx.remove(); tx.close(); } } else { if (tx.isReadOnly()) { throw new IllegalStateException("Cannot start a transaction while a read only transaction is active"); } runnable.run(); } }
protected Cursor(Transaction tx, long cursor, EntityInfo entityInfo, BoxStore boxStore) { if (tx == null) { throw new IllegalArgumentException("Transaction is null"); } this.tx = tx; readOnly = tx.isReadOnly(); this.cursor = cursor; this.entityInfo = entityInfo; this.boxStoreForEntities = boxStore; Property[] allProperties = entityInfo.getAllProperties(); for (Property property : allProperties) { if (!property.isIdVerified()) { int id = getPropertyId(property.dbName); property.verifyId(id); } } creationThrowable = TRACK_CREATION_STACK ? new Throwable() : null; nativeSetBoxStoreForEntities(cursor, boxStore); }
assertEquals(true, txRead.isReadOnly()); assertEquals(false, txWrite.isReadOnly());