Add helper method for running a DB task and logging any exception it throws.

This commit is contained in:
akwizgran
2021-01-26 13:51:03 +00:00
parent 635008fb60
commit c1e83b22c1
16 changed files with 195 additions and 327 deletions

View File

@@ -0,0 +1,6 @@
package org.briarproject.bramble.api;
public interface ThrowingRunnable<T extends Throwable> {
void run() throws T;
}

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.sync; package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.ThrowingRunnable;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.sync; package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.ThrowingRunnable;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;

View File

@@ -1,6 +0,0 @@
package org.briarproject.bramble.sync;
interface ThrowingRunnable<T extends Throwable> {
void run() throws T;
}

View File

@@ -45,10 +45,8 @@ import androidx.arch.core.util.Function;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@NotNullByDefault @NotNullByDefault
@@ -173,14 +171,9 @@ class ContactListViewModel extends DbViewModel implements EventListener {
} }
void checkForPendingContacts() { void checkForPendingContacts() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { boolean hasPending = !contactManager.getPendingContacts().isEmpty();
boolean hasPending = hasPendingContacts.postValue(hasPending);
!contactManager.getPendingContacts().isEmpty();
hasPendingContacts.postValue(hasPending);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }

View File

@@ -66,15 +66,10 @@ public class AddContactViewModel extends DbViewModel {
} }
private void loadHandshakeLink() { private void loadHandshakeLink() {
runOnDbThread(() -> { // If an exception is thrown the UI should stay disabled,
try { // leaving the user unable to proceed
handshakeLink.postValue(contactManager.getHandshakeLink()); runOnDbThreadOrLogException(() ->
} catch (DbException e) { handshakeLink.postValue(contactManager.getHandshakeLink()));
logException(LOG, WARNING, e);
// the UI should stay disabled in this case,
// leaving the user unable to proceed
}
});
} }
LiveData<String> getHandshakeLink() { LiveData<String> getHandshakeLink() {

View File

@@ -10,7 +10,6 @@ import org.briarproject.bramble.api.contact.PendingContactState;
import org.briarproject.bramble.api.contact.event.PendingContactRemovedEvent; import org.briarproject.bramble.api.contact.event.PendingContactRemovedEvent;
import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent; import org.briarproject.bramble.api.contact.event.PendingContactStateChangedEvent;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.TransactionManager; import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
@@ -33,10 +32,8 @@ import javax.inject.Inject;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.contact.PendingContactState.OFFLINE; import static org.briarproject.bramble.api.contact.PendingContactState.OFFLINE;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
public class PendingContactListViewModel extends DbViewModel public class PendingContactListViewModel extends DbViewModel
@@ -90,24 +87,20 @@ public class PendingContactListViewModel extends DbViewModel
} }
private void loadPendingContacts() { private void loadPendingContacts() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { Collection<Pair<PendingContact, PendingContactState>> pairs =
Collection<Pair<PendingContact, PendingContactState>> pairs = contactManager.getPendingContacts();
contactManager.getPendingContacts(); List<PendingContactItem> items = new ArrayList<>(pairs.size());
List<PendingContactItem> items = new ArrayList<>(pairs.size()); boolean online = pairs.isEmpty();
boolean online = pairs.isEmpty(); for (Pair<PendingContact, PendingContactState> pair : pairs) {
for (Pair<PendingContact, PendingContactState> pair : pairs) { PendingContact p = pair.getFirst();
PendingContact p = pair.getFirst(); PendingContactState state = pair.getSecond();
PendingContactState state = pair.getSecond(); long lastPoll = rendezvousPoller.getLastPollTime(p.getId());
long lastPoll = rendezvousPoller.getLastPollTime(p.getId()); items.add(new PendingContactItem(p, state, lastPoll));
items.add(new PendingContactItem(p, state, lastPoll)); online = online || state != OFFLINE;
online = online || state != OFFLINE;
}
pendingContacts.postValue(items);
hasInternetConnection.postValue(online);
} catch (DbException e) {
logException(LOG, WARNING, e);
} }
pendingContacts.postValue(items);
hasInternetConnection.postValue(online);
}); });
} }
@@ -116,13 +109,8 @@ public class PendingContactListViewModel extends DbViewModel
} }
void removePendingContact(PendingContactId id) { void removePendingContact(PendingContactId id) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() ->
try { contactManager.removePendingContact(id));
contactManager.removePendingContact(id);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
} }
LiveData<Boolean> getHasInternetConnection() { LiveData<Boolean> getHasInternetConnection() {

View File

@@ -212,26 +212,18 @@ public class ConversationViewModel extends DbViewModel
} }
void markMessageRead(GroupId g, MessageId m) { void markMessageRead(GroupId g, MessageId m) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { long start = now();
long start = now(); messagingManager.setReadFlag(g, m, true);
messagingManager.setReadFlag(g, m, true); logDuration(LOG, "Marking read", start);
logDuration(LOG, "Marking read", start);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
void setContactAlias(String alias) { void setContactAlias(String alias) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { contactManager.setContactAlias(requireNonNull(contactId),
contactManager.setContactAlias(requireNonNull(contactId), alias.isEmpty() ? null : alias);
alias.isEmpty() ? null : alias); loadContact(contactId);
loadContact(contactId);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@@ -327,21 +319,17 @@ public class ConversationViewModel extends DbViewModel
@UiThread @UiThread
private void storeMessage(PrivateMessage m) { private void storeMessage(PrivateMessage m) {
attachmentCreator.onAttachmentsSent(m.getMessage().getId()); attachmentCreator.onAttachmentsSent(m.getMessage().getId());
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { long start = now();
long start = now(); messagingManager.addLocalMessage(m);
messagingManager.addLocalMessage(m); logDuration(LOG, "Storing message", start);
logDuration(LOG, "Storing message", start); Message message = m.getMessage();
Message message = m.getMessage(); PrivateMessageHeader h = new PrivateMessageHeader(
PrivateMessageHeader h = new PrivateMessageHeader( message.getId(), message.getGroupId(),
message.getId(), message.getGroupId(), message.getTimestamp(), true, true, false, false,
message.getTimestamp(), true, true, false, false, m.hasText(), m.getAttachmentHeaders());
m.hasText(), m.getAttachmentHeaders()); // TODO add text to cache when available here
// TODO add text to cache when available here addedHeader.postEvent(h);
addedHeader.postEvent(h);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@@ -383,12 +371,7 @@ public class ConversationViewModel extends DbViewModel
@UiThread @UiThread
void recheckFeaturesAndOnboarding(ContactId contactId) { void recheckFeaturesAndOnboarding(ContactId contactId) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() ->
try { checkFeaturesAndOnboarding(contactId));
checkFeaturesAndOnboarding(contactId);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
} }
} }

View File

@@ -40,10 +40,8 @@ import androidx.annotation.UiThread;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID; import static org.briarproject.briar.api.forum.ForumManager.CLIENT_ID;
@@ -164,15 +162,11 @@ class ForumListViewModel extends DbViewModel implements EventListener {
} }
void loadForumInvitations() { void loadForumInvitations() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { long start = now();
long start = now(); int available = forumSharingManager.getInvitations().size();
int available = forumSharingManager.getInvitations().size(); logDuration(LOG, "Loading available", start);
logDuration(LOG, "Loading available", start); numInvitations.postValue(available);
numInvitations.postValue(available);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }

View File

@@ -51,10 +51,8 @@ import androidx.lifecycle.MutableLiveData;
import static android.widget.Toast.LENGTH_SHORT; import static android.widget.Toast.LENGTH_SHORT;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -122,14 +120,8 @@ class ForumViewModel extends ThreadListViewModel<ForumPostItem> {
LiveData<Forum> loadForum() { LiveData<Forum> loadForum() {
MutableLiveData<Forum> forum = new MutableLiveData<>(); MutableLiveData<Forum> forum = new MutableLiveData<>();
runOnDbThread(() -> { runOnDbThreadOrLogException(() ->
try { forum.postValue(forumManager.getForum(groupId)));
Forum f = forumManager.getForum(groupId);
forum.postValue(f);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
return forum; return forum;
} }
@@ -147,16 +139,12 @@ class ForumViewModel extends ThreadListViewModel<ForumPostItem> {
@Override @Override
public void createAndStoreMessage(String text, public void createAndStoreMessage(String text,
@Nullable MessageId parentId) { @Nullable MessageId parentId) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { LocalAuthor author = identityManager.getLocalAuthor();
LocalAuthor author = identityManager.getLocalAuthor(); GroupCount count = forumManager.getGroupCount(groupId);
GroupCount count = forumManager.getGroupCount(groupId); long timestamp = max(count.getLatestMsgTime() + 1,
long timestamp = max(count.getLatestMsgTime() + 1, clock.currentTimeMillis());
clock.currentTimeMillis()); createMessage(text, timestamp, parentId, author);
createMessage(text, timestamp, parentId, author);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@@ -171,15 +159,11 @@ class ForumViewModel extends ThreadListViewModel<ForumPostItem> {
} }
private void storePost(ForumPost msg, String text) { private void storePost(ForumPost msg, String text) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { long start = now();
long start = now(); ForumPostHeader header = forumManager.addLocalPost(msg);
ForumPostHeader header = forumManager.addLocalPost(msg); addItemAsync(buildItem(header, text));
addItemAsync(buildItem(header, text)); logDuration(LOG, "Storing forum post", start);
logDuration(LOG, "Storing forum post", start);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@@ -195,39 +179,23 @@ class ForumViewModel extends ThreadListViewModel<ForumPostItem> {
@Override @Override
protected void markItemRead(ForumPostItem item) { protected void markItemRead(ForumPostItem item) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() ->
try { forumManager.setReadFlag(groupId, item.getId(), true));
forumManager.setReadFlag(groupId, item.getId(), true);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
} }
public void loadSharingContacts() { public void loadSharingContacts() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { Collection<Contact> contacts =
Collection<Contact> contacts = forumSharingManager.getSharedWith(groupId);
forumSharingManager.getSharedWith(groupId); Collection<ContactId> contactIds = new ArrayList<>(contacts.size());
Collection<ContactId> contactIds = for (Contact c : contacts) contactIds.add(c.getId());
new ArrayList<>(contacts.size()); sharingController.addAll(contactIds);
for (Contact c : contacts) contactIds.add(c.getId());
sharingController.addAll(contactIds);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
void deleteForum() { void deleteForum() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() ->
try { forumManager.removeForum(forumManager.getForum(groupId)));
Forum f = forumManager.getForum(groupId);
forumManager.removeForum(f);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
Toast.makeText(getApplication(), R.string.forum_left_toast, Toast.makeText(getApplication(), R.string.forum_left_toast,
LENGTH_SHORT).show(); LENGTH_SHORT).show();
} }

View File

@@ -66,34 +66,27 @@ public class NavDrawerViewModel extends DbViewModel {
@UiThread @UiThread
void checkExpiryWarning() { void checkExpiryWarning() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { Settings settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
Settings settings = int warningInt = settings.getInt(EXPIRY_DATE_WARNING, 0);
settingsManager.getSettings(SETTINGS_NAMESPACE);
int warningInt = settings.getInt(EXPIRY_DATE_WARNING, 0);
if (warningInt == 0) { if (warningInt == 0) {
// we have not warned before // we have not warned before
showExpiryWarning.postValue(true);
} else {
long warningLong = warningInt * 1000L;
long now = System.currentTimeMillis();
long daysSinceLastWarning =
(now - warningLong) / DAYS.toMillis(1);
long daysBeforeExpiry = (EXPIRY_DATE - now) / DAYS.toMillis(1);
if (daysSinceLastWarning >= 30) {
showExpiryWarning.postValue(true);
} else if (daysBeforeExpiry <= 3 && daysSinceLastWarning > 0) {
showExpiryWarning.postValue(true); showExpiryWarning.postValue(true);
} else { } else {
long warningLong = warningInt * 1000L; showExpiryWarning.postValue(false);
long now = System.currentTimeMillis();
long daysSinceLastWarning =
(now - warningLong) / DAYS.toMillis(1);
long daysBeforeExpiry =
(EXPIRY_DATE - now) / DAYS.toMillis(1);
if (daysSinceLastWarning >= 30) {
showExpiryWarning.postValue(true);
} else if (daysBeforeExpiry <= 3 &&
daysSinceLastWarning > 0) {
showExpiryWarning.postValue(true);
} else {
showExpiryWarning.postValue(false);
}
} }
} catch (DbException e) {
logException(LOG, WARNING, e);
} }
}); });
} }
@@ -101,15 +94,11 @@ public class NavDrawerViewModel extends DbViewModel {
@UiThread @UiThread
void expiryWarningDismissed() { void expiryWarningDismissed() {
showExpiryWarning.setValue(false); showExpiryWarning.setValue(false);
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { Settings settings = new Settings();
Settings settings = new Settings(); int date = (int) (System.currentTimeMillis() / 1000L);
int date = (int) (System.currentTimeMillis() / 1000L); settings.putInt(EXPIRY_DATE_WARNING, date);
settings.putInt(EXPIRY_DATE_WARNING, date); settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@@ -145,30 +134,21 @@ public class NavDrawerViewModel extends DbViewModel {
@UiThread @UiThread
void checkTransportsOnboarding() { void checkTransportsOnboarding() {
if (showTransportsOnboarding.getValue() != null) return; if (showTransportsOnboarding.getValue() != null) return;
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { Settings settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
Settings settings = boolean show =
settingsManager.getSettings(SETTINGS_NAMESPACE); settings.getBoolean(SHOW_TRANSPORTS_ONBOARDING, true);
boolean show = showTransportsOnboarding.postValue(show);
settings.getBoolean(SHOW_TRANSPORTS_ONBOARDING, true);
showTransportsOnboarding.postValue(show);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@UiThread @UiThread
void transportsOnboardingShown() { void transportsOnboardingShown() {
showTransportsOnboarding.setValue(false); showTransportsOnboarding.setValue(false);
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { Settings settings = new Settings();
Settings settings = new Settings(); settings.putBoolean(SHOW_TRANSPORTS_ONBOARDING, false);
settings.putBoolean(SHOW_TRANSPORTS_ONBOARDING, false); settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
} }

View File

@@ -45,12 +45,10 @@ import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE; import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
import static android.bluetooth.BluetoothAdapter.STATE_ON; import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.Plugin.PREF_PLUGIN_ENABLE; import static org.briarproject.bramble.api.plugin.Plugin.PREF_PLUGIN_ENABLE;
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@NotNullByDefault @NotNullByDefault
@@ -185,20 +183,16 @@ public class PluginViewModel extends DbViewModel implements EventListener {
} }
private void loadSettings() { private void loadSettings() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { boolean tor = isPluginEnabled(TorConstants.ID,
boolean tor = isPluginEnabled(TorConstants.ID, TorConstants.DEFAULT_PREF_PLUGIN_ENABLE);
TorConstants.DEFAULT_PREF_PLUGIN_ENABLE); torEnabledSetting.postValue(tor);
torEnabledSetting.postValue(tor); boolean wifi = isPluginEnabled(LanTcpConstants.ID,
boolean wifi = isPluginEnabled(LanTcpConstants.ID, LanTcpConstants.DEFAULT_PREF_PLUGIN_ENABLE);
LanTcpConstants.DEFAULT_PREF_PLUGIN_ENABLE); wifiEnabledSetting.postValue(wifi);
wifiEnabledSetting.postValue(wifi); boolean bt = isPluginEnabled(BluetoothConstants.ID,
boolean bt = isPluginEnabled(BluetoothConstants.ID, BluetoothConstants.DEFAULT_PREF_PLUGIN_ENABLE);
BluetoothConstants.DEFAULT_PREF_PLUGIN_ENABLE); btEnabledSetting.postValue(bt);
btEnabledSetting.postValue(bt);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@@ -222,14 +216,10 @@ public class PluginViewModel extends DbViewModel implements EventListener {
} }
private void mergeSettings(Settings s, String namespace) { private void mergeSettings(Settings s, String namespace) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { long start = now();
long start = now(); settingsManager.mergeSettings(s, namespace);
settingsManager.mergeSettings(s, namespace); logDuration(LOG, "Merging settings", start);
logDuration(LOG, "Merging settings", start);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }

View File

@@ -52,10 +52,8 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -143,15 +141,11 @@ class GroupViewModel extends ThreadListViewModel<GroupMessageItem> {
} }
private void loadPrivateGroup(GroupId groupId) { private void loadPrivateGroup(GroupId groupId) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { PrivateGroup g = privateGroupManager.getPrivateGroup(groupId);
PrivateGroup g = privateGroupManager.getPrivateGroup(groupId); privateGroup.postValue(g);
privateGroup.postValue(g); Author author = identityManager.getLocalAuthor();
Author author = identityManager.getLocalAuthor(); isCreator.postValue(g.getCreator().equals(author));
isCreator.postValue(g.getCreator().equals(author));
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@@ -190,18 +184,14 @@ class GroupViewModel extends ThreadListViewModel<GroupMessageItem> {
@Override @Override
public void createAndStoreMessage(String text, public void createAndStoreMessage(String text,
@Nullable MessageId parentId) { @Nullable MessageId parentId) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { LocalAuthor author = identityManager.getLocalAuthor();
LocalAuthor author = identityManager.getLocalAuthor(); MessageId previousMsgId =
MessageId previousMsgId = privateGroupManager.getPreviousMsgId(groupId);
privateGroupManager.getPreviousMsgId(groupId); GroupCount count = privateGroupManager.getGroupCount(groupId);
GroupCount count = privateGroupManager.getGroupCount(groupId); long timestamp = count.getLatestMsgTime();
long timestamp = count.getLatestMsgTime(); timestamp = max(clock.currentTimeMillis(), timestamp + 1);
timestamp = max(clock.currentTimeMillis(), timestamp + 1); createMessage(text, timestamp, parentId, author, previousMsgId);
createMessage(text, timestamp, parentId, author, previousMsgId);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@@ -217,55 +207,36 @@ class GroupViewModel extends ThreadListViewModel<GroupMessageItem> {
} }
private void storePost(GroupMessage msg, String text) { private void storePost(GroupMessage msg, String text) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { long start = now();
long start = now(); GroupMessageHeader header =
GroupMessageHeader header = privateGroupManager.addLocalMessage(msg);
privateGroupManager.addLocalMessage(msg); addItemAsync(buildItem(header, text));
addItemAsync(buildItem(header, text)); logDuration(LOG, "Storing group message", start);
logDuration(LOG, "Storing group message", start);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
@Override @Override
protected void markItemRead(GroupMessageItem item) { protected void markItemRead(GroupMessageItem item) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() ->
try { privateGroupManager.setReadFlag(groupId, item.getId(), true));
privateGroupManager.setReadFlag(groupId, item.getId(), true);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
} }
public void loadSharingContacts() { public void loadSharingContacts() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { Collection<GroupMember> members =
Collection<GroupMember> members = privateGroupManager.getMembers(groupId);
privateGroupManager.getMembers(groupId); Collection<ContactId> contactIds = new ArrayList<>();
Collection<ContactId> contactIds = new ArrayList<>(); for (GroupMember m : members) {
for (GroupMember m : members) { if (m.getContactId() != null) contactIds.add(m.getContactId());
if (m.getContactId() != null)
contactIds.add(m.getContactId());
}
sharingController.addAll(contactIds);
} catch (DbException e) {
logException(LOG, WARNING, e);
} }
sharingController.addAll(contactIds);
}); });
} }
void deletePrivateGroup() { void deletePrivateGroup() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() ->
try { privateGroupManager.removePrivateGroup(groupId));
privateGroupManager.removePrivateGroup(groupId);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
} }
LiveData<PrivateGroup> getPrivateGroup() { LiveData<PrivateGroup> getPrivateGroup() {

View File

@@ -2,7 +2,6 @@ package org.briarproject.briar.android.privategroup.list;
import android.app.Application; import android.app.Application;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
@@ -49,10 +48,8 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID; import static org.briarproject.briar.api.privategroup.PrivateGroupManager.CLIENT_ID;
@@ -200,25 +197,17 @@ class GroupListViewModel extends DbViewModel implements EventListener {
} }
void removeGroup(GroupId g) { void removeGroup(GroupId g) {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { long start = now();
long start = now(); groupManager.removePrivateGroup(g);
groupManager.removePrivateGroup(g); logDuration(LOG, "Removing group", start);
logDuration(LOG, "Removing group", start);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }
void loadNumInvitations() { void loadNumInvitations() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { int i = groupInvitationManager.getInvitations().size();
int i = groupInvitationManager.getInvitations().size(); numInvitations.postValue(i);
numInvitations.postValue(i);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}); });
} }

View File

@@ -44,10 +44,8 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -145,16 +143,11 @@ public abstract class ThreadListViewModel<I extends ThreadItem>
} }
private void loadStoredMessageId() { private void loadStoredMessageId() {
runOnDbThread(() -> { runOnDbThreadOrLogException(() -> {
try { storedMessageId.set(messageTracker.loadStoredMessageId(groupId));
storedMessageId if (LOG.isLoggable(INFO)) {
.set(messageTracker.loadStoredMessageId(groupId)); LOG.info("Loaded last top visible message id " +
if (LOG.isLoggable(INFO)) { storedMessageId);
LOG.info("Loaded last top visible message id " +
storedMessageId);
}
} catch (DbException e) {
logException(LOG, WARNING, e);
} }
}); });
} }
@@ -229,13 +222,10 @@ public abstract class ThreadListViewModel<I extends ThreadItem>
} }
void storeMessageId(@Nullable MessageId messageId) { void storeMessageId(@Nullable MessageId messageId) {
if (messageId != null) runOnDbThread(() -> { if (messageId != null) {
try { runOnDbThreadOrLogException(() ->
messageTracker.storeMessageId(groupId, messageId); messageTracker.storeMessageId(groupId, messageId));
} catch (DbException e) { }
logException(LOG, WARNING, e);
}
});
} }
protected abstract void markItemRead(I item); protected abstract void markItemRead(I item);

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.android.viewmodel;
import android.app.Application; import android.app.Application;
import org.briarproject.bramble.api.ThrowingRunnable;
import org.briarproject.bramble.api.db.DatabaseExecutor; import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbCallable; import org.briarproject.bramble.api.db.DbCallable;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
@@ -76,6 +77,30 @@ public abstract class DbViewModel extends AndroidViewModel {
}); });
} }
/**
* Runs the given task on the {@link DatabaseExecutor}
* and waits for the DB to open. If the task throws a {@link DbException}
* it's caught and logged.
* <p>
* If you need a list of items to be displayed in a
* {@link RecyclerView.Adapter},
* use {@link #loadList(DbCallable, UiConsumer)} instead.
*/
protected void runOnDbThreadOrLogException(
ThrowingRunnable<DbException> task) {
dbExecutor.execute(() -> {
try {
lifecycleManager.waitForDatabase();
task.run();
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting for database");
Thread.currentThread().interrupt();
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
/** /**
* Loads a list of items on the {@link DatabaseExecutor} within a single * Loads a list of items on the {@link DatabaseExecutor} within a single
* {@link Transaction} and publishes it as a {@link LiveResult} * {@link Transaction} and publishes it as a {@link LiveResult}