Load list of private groups in a single DB transaction

This commit is contained in:
Torsten Grote
2020-12-17 13:11:13 -03:00
parent 9048392d4e
commit fd86b73626
4 changed files with 87 additions and 46 deletions

View File

@@ -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();

View File

@@ -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<Collection<GroupItem>, DbException> handler) {
runOnDbThread(() -> {
try {
long start = now();
Collection<PrivateGroup> groups =
groupManager.getPrivateGroups();
List<GroupItem> items = new ArrayList<>(groups.size());
Map<AuthorId, AuthorInfo> 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<Collection<GroupItem>, DbException> handler)
throws DbException {
long start = now();
Collection<PrivateGroup> groups = groupManager.getPrivateGroups(txn);
List<GroupItem> items = new ArrayList<>(groups.size());
Map<AuthorId, AuthorInfo> 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<DbException> handler) {
runOnDbThread(() -> {

View File

@@ -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<PrivateGroup> getPrivateGroups() throws DbException;
/**
* Returns all private groups the user is a member of.
*/
Collection<PrivateGroup> 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.
*/

View File

@@ -270,22 +270,31 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
}
@Override
public Collection<PrivateGroup> getPrivateGroups() throws DbException {
Collection<Group> groups;
Transaction txn = db.startTransaction(true);
public Collection<PrivateGroup> getPrivateGroups(Transaction txn)
throws DbException {
Collection<Group> groups = db.getGroups(txn, CLIENT_ID, MAJOR_VERSION);
Collection<PrivateGroup> privateGroups = new ArrayList<>(groups.size());
try {
groups = db.getGroups(txn, CLIENT_ID, MAJOR_VERSION);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
try {
Collection<PrivateGroup> 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<PrivateGroup> 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<Author, Visibility> 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);