From 3bcc532b4b68fdeab4b4ea8778b8253d7a618b67 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Wed, 15 Nov 2017 10:11:39 +0000 Subject: [PATCH 1/4] Add transactional DB interface. --- .../bramble/api/db/DatabaseComponent.java | 26 +++++++++++++ .../bramble/api/db/DbCallable.java | 6 +++ .../bramble/api/db/DbRunnable.java | 6 +++ .../bramble/db/DatabaseComponentImpl.java | 39 +++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/db/DbCallable.java create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/db/DbRunnable.java 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()); From 7359b6942a766af468171d357b79f491ac884c94 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 4 Oct 2018 15:59:10 +0100 Subject: [PATCH 2/4] Use transactional DB interface for ForumManagerImpl. --- .../briar/forum/ForumManagerImpl.java | 124 +++++++----------- 1 file changed, 48 insertions(+), 76 deletions(-) diff --git a/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java index 58b35ea65..f2fddf0cf 100644 --- a/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java @@ -94,14 +94,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { @Override public Forum addForum(String name) throws DbException { Forum f = forumFactory.createForum(name); - - Transaction txn = db.startTransaction(false); - try { - db.addGroup(txn, f.getGroup()); - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } + db.transaction(false, txn -> db.addGroup(txn, f.getGroup())); return f; } @@ -112,15 +105,11 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { @Override public void removeForum(Forum f) throws DbException { - Transaction txn = db.startTransaction(false); - try { + db.transaction(false, txn -> { for (RemoveForumHook hook : removeHooks) hook.removingForum(txn, f); db.removeGroup(txn, f.getGroup()); - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } + }); } @Override @@ -131,45 +120,35 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { p = forumPostFactory.createPost(groupId, timestamp, parentId, author, body); } catch (GeneralSecurityException | FormatException e) { - throw new RuntimeException(e); + throw new AssertionError(e); } return p; } @Override public ForumPostHeader addLocalPost(ForumPost p) throws DbException { - Transaction txn = db.startTransaction(false); - try { - BdfDictionary meta = new BdfDictionary(); - meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp()); - if (p.getParent() != null) meta.put(KEY_PARENT, p.getParent()); - Author a = p.getAuthor(); - meta.put(KEY_AUTHOR, clientHelper.toList(a)); - meta.put(KEY_LOCAL, true); - meta.put(MSG_KEY_READ, true); - clientHelper.addLocalMessage(txn, p.getMessage(), meta, true); - messageTracker.trackOutgoingMessage(txn, p.getMessage()); - db.commitTransaction(txn); - } catch (FormatException e) { - throw new RuntimeException(e); - } finally { - db.endTransaction(txn); - } + db.transaction(false, txn -> { + try { + BdfDictionary meta = new BdfDictionary(); + meta.put(KEY_TIMESTAMP, p.getMessage().getTimestamp()); + if (p.getParent() != null) meta.put(KEY_PARENT, p.getParent()); + Author a = p.getAuthor(); + meta.put(KEY_AUTHOR, clientHelper.toList(a)); + meta.put(KEY_LOCAL, true); + meta.put(MSG_KEY_READ, true); + clientHelper.addLocalMessage(txn, p.getMessage(), meta, true); + messageTracker.trackOutgoingMessage(txn, p.getMessage()); + } catch (FormatException e) { + throw new AssertionError(e); + } + }); return new ForumPostHeader(p.getMessage().getId(), p.getParent(), p.getMessage().getTimestamp(), p.getAuthor(), OURSELVES, true); } @Override public Forum getForum(GroupId g) throws DbException { - Forum forum; - Transaction txn = db.startTransaction(true); - try { - forum = getForum(txn, g); - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } - return forum; + return db.transactionWithResult(true, txn -> getForum(txn, g)); } @Override @@ -184,15 +163,9 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { @Override public Collection getForums() throws DbException { + Collection groups = db.transactionWithResult(true, txn -> + db.getGroups(txn, CLIENT_ID, MAJOR_VERSION)); try { - Collection groups; - Transaction txn = db.startTransaction(true); - try { - groups = db.getGroups(txn, CLIENT_ID, MAJOR_VERSION); - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } List forums = new ArrayList<>(); for (Group g : groups) forums.add(parseForum(g)); return forums; @@ -218,36 +191,35 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { @Override public Collection getPostHeaders(GroupId g) throws DbException { - - Collection headers = new ArrayList<>(); - Transaction txn = db.startTransaction(true); try { - Map metadata = - clientHelper.getMessageMetadataAsDictionary(txn, g); - // get all authors we need to get the status for - Set authors = new HashSet<>(); - for (Entry entry : metadata.entrySet()) { - BdfList authorList = entry.getValue().getList(KEY_AUTHOR); - Author a = clientHelper.parseAndValidateAuthor(authorList); - authors.add(a.getId()); - } - // get statuses for all authors - Map statuses = new HashMap<>(); - for (AuthorId id : authors) { - statuses.put(id, identityManager.getAuthorStatus(txn, id)); - } - // Parse the metadata - for (Entry entry : metadata.entrySet()) { - BdfDictionary meta = entry.getValue(); - headers.add(getForumPostHeader(txn, entry.getKey(), meta, - statuses)); - } - db.commitTransaction(txn); - return headers; + return db.throwingTransactionWithResult(true, txn -> { + Collection headers = new ArrayList<>(); + Map metadata = + clientHelper.getMessageMetadataAsDictionary(txn, g); + // get all authors we need to get the status for + Set authors = new HashSet<>(); + for (Entry entry : + metadata.entrySet()) { + BdfList authorList = entry.getValue().getList(KEY_AUTHOR); + Author a = clientHelper.parseAndValidateAuthor(authorList); + authors.add(a.getId()); + } + // get statuses for all authors + Map statuses = new HashMap<>(); + for (AuthorId id : authors) { + statuses.put(id, identityManager.getAuthorStatus(txn, id)); + } + // Parse the metadata + for (Entry entry : + metadata.entrySet()) { + BdfDictionary meta = entry.getValue(); + headers.add(getForumPostHeader(txn, entry.getKey(), meta, + statuses)); + } + return headers; + }); } catch (FormatException e) { throw new DbException(e); - } finally { - db.endTransaction(txn); } } From 2623eaa149e07ccb65db43536de98f1b2d7afbe2 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 5 Oct 2018 09:32:01 +0100 Subject: [PATCH 3/4] Remove unnecessary throwing variants. --- .../bramble/api/db/DatabaseComponent.java | 17 ++--------------- .../bramble/db/DatabaseComponentImpl.java | 18 +++--------------- .../briar/forum/ForumManagerImpl.java | 2 +- 3 files changed, 6 insertions(+), 31 deletions(-) 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 56a3391dd..3fff5f9d6 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 @@ -79,27 +79,14 @@ public interface DatabaseComponent { /** * 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, + void transaction(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, + R transactionWithResult(boolean readOnly, DbCallable task) 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 ad867dfb4..c4b303fbb 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 @@ -169,19 +169,7 @@ class DatabaseComponentImpl implements DatabaseComponent { } @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, + public void transaction(boolean readOnly, DbRunnable task) throws DbException, E { final Transaction txn = startTransaction(readOnly); try { @@ -193,8 +181,8 @@ class DatabaseComponentImpl implements DatabaseComponent { } @Override - public R throwingTransactionWithResult( - boolean readOnly, DbCallable task) throws DbException, E { + public R transactionWithResult(boolean readOnly, + DbCallable task) throws DbException, E { final Transaction txn = startTransaction(readOnly); try { R result = task.call(txn); diff --git a/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java index f2fddf0cf..b60e7c94b 100644 --- a/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/forum/ForumManagerImpl.java @@ -192,7 +192,7 @@ class ForumManagerImpl extends BdfIncomingMessageHook implements ForumManager { public Collection getPostHeaders(GroupId g) throws DbException { try { - return db.throwingTransactionWithResult(true, txn -> { + return db.transactionWithResult(true, txn -> { Collection headers = new ArrayList<>(); Map metadata = clientHelper.getMessageMetadataAsDictionary(txn, g); From bc298ba68ac574a396d44587d67708da91962047 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Fri, 5 Oct 2018 09:34:41 +0100 Subject: [PATCH 4/4] Remove unnecessary final modifiers. --- .../org/briarproject/bramble/db/DatabaseComponentImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 c4b303fbb..829433ba5 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 @@ -171,7 +171,7 @@ class DatabaseComponentImpl implements DatabaseComponent { @Override public void transaction(boolean readOnly, DbRunnable task) throws DbException, E { - final Transaction txn = startTransaction(readOnly); + Transaction txn = startTransaction(readOnly); try { task.run(txn); commitTransaction(txn); @@ -183,7 +183,7 @@ class DatabaseComponentImpl implements DatabaseComponent { @Override public R transactionWithResult(boolean readOnly, DbCallable task) throws DbException, E { - final Transaction txn = startTransaction(readOnly); + Transaction txn = startTransaction(readOnly); try { R result = task.call(txn); commitTransaction(txn);