diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index aec77c5aa..56a3391dd 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -76,6 +76,32 @@ public interface DatabaseComponent { */ void endTransaction(Transaction txn); + /** + * Runs the given task within a transaction. + */ + void transaction(boolean readOnly, DbRunnable task) + throws DbException; + + /** + * Runs the given task within a transaction and returns the result of the + * task. + */ + R transactionWithResult(boolean readOnly, + DbCallable task) throws DbException; + + /** + * Runs the given task within a transaction. + */ + void throwingTransaction(boolean readOnly, + DbRunnable task) throws DbException, E; + + /** + * Runs the given task within a transaction and returns the result of the + * task. + */ + R throwingTransactionWithResult(boolean readOnly, + DbCallable task) throws DbException, E; + /** * Stores a contact associated with the given local and remote pseudonyms, * and returns an ID for the contact. diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbCallable.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbCallable.java new file mode 100644 index 000000000..d90a2e9e4 --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbCallable.java @@ -0,0 +1,6 @@ +package org.briarproject.bramble.api.db; + +public interface DbCallable { + + R call(Transaction txn) throws DbException, E; +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbRunnable.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbRunnable.java new file mode 100644 index 000000000..64d36143c --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DbRunnable.java @@ -0,0 +1,6 @@ +package org.briarproject.bramble.api.db; + +public interface DbRunnable { + + void run(Transaction txn) throws DbException, E; +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 99f9e7c10..ad867dfb4 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -9,7 +9,9 @@ import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.ContactExistsException; import org.briarproject.bramble.api.db.DatabaseComponent; +import org.briarproject.bramble.api.db.DbCallable; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.DbRunnable; import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.NoSuchContactException; @@ -166,6 +168,43 @@ class DatabaseComponentImpl implements DatabaseComponent { for (Event e : transaction.getEvents()) eventBus.broadcast(e); } + @Override + public void transaction(boolean readOnly, DbRunnable task) + throws DbException { + throwingTransaction(readOnly, task); + } + + @Override + public R transactionWithResult(boolean readOnly, + DbCallable task) throws DbException { + return throwingTransactionWithResult(readOnly, task); + } + + @Override + public void throwingTransaction(boolean readOnly, + DbRunnable task) throws DbException, E { + final Transaction txn = startTransaction(readOnly); + try { + task.run(txn); + commitTransaction(txn); + } finally { + endTransaction(txn); + } + } + + @Override + public R throwingTransactionWithResult( + boolean readOnly, DbCallable task) throws DbException, E { + final Transaction txn = startTransaction(readOnly); + try { + R result = task.call(txn); + commitTransaction(txn); + return result; + } finally { + endTransaction(txn); + } + } + private T unbox(Transaction transaction) { if (transaction.isCommitted()) throw new IllegalStateException(); return txnClass.cast(transaction.unbox());