From fd86b736263bdf311e3c96db9e51b90679a66d2f Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 17 Dec 2020 13:11:13 -0300 Subject: [PATCH] Load list of private groups in a single DB transaction --- .../briar/android/AndroidComponent.java | 3 + .../list/GroupListControllerImpl.java | 65 +++++++++++-------- .../api/privategroup/PrivateGroupManager.java | 16 +++++ .../privategroup/PrivateGroupManagerImpl.java | 49 ++++++++------ 4 files changed, 87 insertions(+), 46 deletions(-) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java index b1168d848..6f83e06fc 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java @@ -14,6 +14,7 @@ import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.crypto.CryptoExecutor; import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator; import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.db.TransactionManager; import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.keyagreement.KeyAgreementTask; @@ -85,6 +86,8 @@ public interface AndroidComponent @DatabaseExecutor Executor databaseExecutor(); + TransactionManager transactionManager(); + MessageTracker messageTracker(); LifecycleManager lifecycleManager(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListControllerImpl.java index 51d97095e..5119407eb 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/list/GroupListControllerImpl.java @@ -4,6 +4,8 @@ import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.NoSuchGroupException; +import org.briarproject.bramble.api.db.Transaction; +import org.briarproject.bramble.api.db.TransactionManager; import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventListener; @@ -55,6 +57,7 @@ class GroupListControllerImpl extends DbControllerImpl private static final Logger LOG = Logger.getLogger(GroupListControllerImpl.class.getName()); + private final TransactionManager db; private final PrivateGroupManager groupManager; private final GroupInvitationManager groupInvitationManager; private final ContactManager contactManager; @@ -67,11 +70,14 @@ class GroupListControllerImpl extends DbControllerImpl @Inject GroupListControllerImpl(@DatabaseExecutor Executor dbExecutor, - LifecycleManager lifecycleManager, PrivateGroupManager groupManager, + LifecycleManager lifecycleManager, + TransactionManager db, + PrivateGroupManager groupManager, GroupInvitationManager groupInvitationManager, ContactManager contactManager, AndroidNotificationManager notificationManager, EventBus eventBus) { super(dbExecutor, lifecycleManager); + this.db = db; this.groupManager = groupManager; this.groupInvitationManager = groupInvitationManager; this.contactManager = contactManager; @@ -140,32 +146,7 @@ class GroupListControllerImpl extends DbControllerImpl ResultExceptionHandler, DbException> handler) { runOnDbThread(() -> { try { - long start = now(); - Collection groups = - groupManager.getPrivateGroups(); - List items = new ArrayList<>(groups.size()); - Map authorInfos = new HashMap<>(); - for (PrivateGroup g : groups) { - try { - GroupId id = g.getId(); - AuthorId authorId = g.getCreator().getId(); - AuthorInfo authorInfo; - if (authorInfos.containsKey(authorId)) { - authorInfo = authorInfos.get(authorId); - } else { - authorInfo = contactManager.getAuthorInfo(authorId); - authorInfos.put(authorId, authorInfo); - } - GroupCount count = groupManager.getGroupCount(id); - boolean dissolved = groupManager.isDissolved(id); - items.add( - new GroupItem(g, authorInfo, count, dissolved)); - } catch (NoSuchGroupException e) { - // Continue - } - } - logDuration(LOG, "Loading groups", start); - handler.onResult(items); + db.transaction(true, txn -> loadGroups(txn, handler)); } catch (DbException e) { logException(LOG, WARNING, e); handler.onException(e); @@ -173,6 +154,36 @@ class GroupListControllerImpl extends DbControllerImpl }); } + @DatabaseExecutor + private void loadGroups(Transaction txn, + ResultExceptionHandler, DbException> handler) + throws DbException { + long start = now(); + Collection groups = groupManager.getPrivateGroups(txn); + List items = new ArrayList<>(groups.size()); + Map authorInfos = new HashMap<>(); + for (PrivateGroup g : groups) { + try { + GroupId id = g.getId(); + AuthorId authorId = g.getCreator().getId(); + AuthorInfo authorInfo; + if (authorInfos.containsKey(authorId)) { + authorInfo = authorInfos.get(authorId); + } else { + authorInfo = contactManager.getAuthorInfo(txn, authorId); + authorInfos.put(authorId, authorInfo); + } + GroupCount count = groupManager.getGroupCount(txn, id); + boolean dissolved = groupManager.isDissolved(txn, id); + items.add(new GroupItem(g, authorInfo, count, dissolved)); + } catch (NoSuchGroupException e) { + // Continue + } + } + logDuration(LOG, "Loading groups", start); + handler.onResult(items); + } + @Override public void removeGroup(GroupId g, ExceptionHandler handler) { runOnDbThread(() -> { diff --git a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupManager.java b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupManager.java index d47c49f9a..478b03975 100644 --- a/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupManager.java +++ b/briar-api/src/main/java/org/briarproject/briar/api/privategroup/PrivateGroupManager.java @@ -66,6 +66,11 @@ public interface PrivateGroupManager { */ void markGroupDissolved(Transaction txn, GroupId g) throws DbException; + /** + * Returns true if the given private group has been dissolved. + */ + boolean isDissolved(Transaction txn, GroupId g) throws DbException; + /** * Returns true if the given private group has been dissolved. */ @@ -91,6 +96,12 @@ public interface PrivateGroupManager { */ Collection getPrivateGroups() throws DbException; + /** + * Returns all private groups the user is a member of. + */ + Collection getPrivateGroups(Transaction txn) + throws DbException; + /** * Returns the text of the private group message with the given ID. */ @@ -111,6 +122,11 @@ public interface PrivateGroupManager { */ boolean isMember(Transaction txn, GroupId g, Author a) throws DbException; + /** + * Returns the group count for the given private group. + */ + GroupCount getGroupCount(Transaction txn, GroupId g) throws DbException; + /** * Returns the group count for the given private group. */ diff --git a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java index 27f5fd649..72d1ae12e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/privategroup/PrivateGroupManagerImpl.java @@ -270,22 +270,31 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook } @Override - public Collection getPrivateGroups() throws DbException { - Collection groups; - Transaction txn = db.startTransaction(true); + public Collection getPrivateGroups(Transaction txn) + throws DbException { + Collection groups = db.getGroups(txn, CLIENT_ID, MAJOR_VERSION); + Collection privateGroups = new ArrayList<>(groups.size()); try { - groups = db.getGroups(txn, CLIENT_ID, MAJOR_VERSION); - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } - try { - Collection privateGroups = - new ArrayList<>(groups.size()); for (Group g : groups) { privateGroups.add(privateGroupFactory.parsePrivateGroup(g)); } - return privateGroups; + } catch (FormatException e) { + throw new DbException(e); + } + return privateGroups; + } + + @Override + public Collection getPrivateGroups() throws DbException { + return db.transactionWithResult(true, this::getPrivateGroups); + } + + @Override + public boolean isDissolved(Transaction txn, GroupId g) throws DbException { + try { + BdfDictionary meta = + clientHelper.getGroupMetadataAsDictionary(txn, g); + return meta.getBoolean(GROUP_KEY_DISSOLVED); } catch (FormatException e) { throw new DbException(e); } @@ -293,12 +302,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook @Override public boolean isDissolved(GroupId g) throws DbException { - try { - BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(g); - return meta.getBoolean(GROUP_KEY_DISSOLVED); - } catch (FormatException e) { - throw new DbException(e); - } + return db.transactionWithResult(true, txn -> isDissolved(txn, g)); } @Override @@ -403,7 +407,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook PrivateGroup privateGroup = getPrivateGroup(txn, g); for (Entry m : authors.entrySet()) { Author a = m.getKey(); - AuthorInfo authorInfo = contactManager.getAuthorInfo(txn, a.getId()); + AuthorInfo authorInfo = + contactManager.getAuthorInfo(txn, a.getId()); Status status = authorInfo.getStatus(); Visibility v = m.getValue(); ContactId c = null; @@ -450,6 +455,12 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook return false; } + @Override + public GroupCount getGroupCount(Transaction txn, GroupId g) + throws DbException { + return messageTracker.getGroupCount(txn, g); + } + @Override public GroupCount getGroupCount(GroupId g) throws DbException { return messageTracker.getGroupCount(g);