From 013822fe82906232dcd10534db16e932522a0963 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 16 Nov 2017 15:53:03 +0100 Subject: [PATCH] excute db read and writes on different threads --- .../crypto/axolotl/AxolotlService.java | 2 +- .../conversations/entities/Conversation.java | 4 +-- .../services/XmppConnectionService.java | 25 ++++++++++--------- .../ReplacingSerialSingleThreadExecutor.java | 2 +- .../utils/SerialSingleThreadExecutor.java | 14 ++++++++--- 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 5197c419a..79b9625b6 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -276,7 +276,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { this.messageCache = new HashMap<>(); this.sessions = new SessionMap(mXmppConnectionService, axolotlStore, account); this.fetchStatusMap = new FetchStatusMap(); - this.executor = new SerialSingleThreadExecutor(); + this.executor = new SerialSingleThreadExecutor("Axolotl"); } public String getOwnFingerprint() { diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 4aefc95fa..28b51b9af 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -762,7 +762,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl public boolean setNextMessage(String message) { boolean changed = !getNextMessage().equals(message); - this.setAttribute(ATTRIBUTE_NEXT_MESSAGE,message); + this.setAttribute(ATTRIBUTE_NEXT_MESSAGE, message); return changed; } @@ -851,7 +851,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl public boolean setAttribute(String key, String value) { synchronized (this.attributes) { try { - this.attributes.put(key, value); + this.attributes.put(key, value == null ? "" : value); return true; } catch (JSONException e) { return false; diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index 48dac145f..b9fa5744a 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -155,9 +155,10 @@ public class XmppConnectionService extends Service { private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts"; public static final String ACTION_GCM_TOKEN_REFRESH = "gcm_token_refresh"; public static final String ACTION_GCM_MESSAGE_RECEIVED = "gcm_message_received"; - private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor(); - private final SerialSingleThreadExecutor mVideoCompressionExecutor = new SerialSingleThreadExecutor(); - private final SerialSingleThreadExecutor mDatabaseExecutor = new SerialSingleThreadExecutor(); + private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor("FileAdding"); + private final SerialSingleThreadExecutor mVideoCompressionExecutor = new SerialSingleThreadExecutor("VideoCompression"); + private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter"); + private final SerialSingleThreadExecutor mDatabaseReaderExecutor = new SerialSingleThreadExecutor("DatabaseReader"); private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor(true); private final IBinder mBinder = new XmppConnectionBinder(); private final List conversations = new CopyOnWriteArrayList<>(); @@ -874,7 +875,7 @@ public class XmppConnectionService extends Service { public void expireOldMessages(final boolean resetHasMessagesLeftOnServer) { mLastExpiryRun.set(SystemClock.elapsedRealtime()); - mDatabaseExecutor.execute(new Runnable() { + mDatabaseWriterExecutor.execute(new Runnable() { @Override public void run() { long timestamp = getAutomaticMessageDeletionDate(); @@ -1450,7 +1451,7 @@ public class XmppConnectionService extends Service { updateConversationUi(); } }; - mDatabaseExecutor.execute(runnable); + mDatabaseReaderExecutor.execute(runnable); //will contain one write command (expiry) but that's fine } } @@ -1602,7 +1603,7 @@ public class XmppConnectionService extends Service { } } }; - mDatabaseExecutor.execute(runnable); + mDatabaseReaderExecutor.execute(runnable); } public List getAccounts() { @@ -1715,7 +1716,7 @@ public class XmppConnectionService extends Service { } }; if (async) { - mDatabaseExecutor.execute(runnable); + mDatabaseReaderExecutor.execute(runnable); } else { runnable.run(); } @@ -1892,7 +1893,7 @@ public class XmppConnectionService extends Service { } } }; - mDatabaseExecutor.execute(runnable); + mDatabaseWriterExecutor.execute(runnable); this.accounts.remove(account); updateAccountUi(); getNotificationService().updateErrorNotification(); @@ -3082,7 +3083,7 @@ public class XmppConnectionService extends Service { } public void updateConversation(final Conversation conversation) { - mDatabaseExecutor.execute(new Runnable() { + mDatabaseWriterExecutor.execute(new Runnable() { @Override public void run() { databaseBackend.updateConversation(conversation); @@ -3364,7 +3365,7 @@ public class XmppConnectionService extends Service { } } }; - mDatabaseExecutor.execute(runnable); + mDatabaseWriterExecutor.execute(runnable); updateUnreadCountBadge(); return true; } else { @@ -3441,7 +3442,7 @@ public class XmppConnectionService extends Service { databaseBackend.writeRoster(account.getRoster()); } }; - mDatabaseExecutor.execute(runnable); + mDatabaseWriterExecutor.execute(runnable); } @@ -3662,7 +3663,7 @@ public class XmppConnectionService extends Service { databaseBackend.updateConversation(conversation); } }; - mDatabaseExecutor.execute(runnable); + mDatabaseWriterExecutor.execute(runnable); } public boolean sendBlockRequest(final Blockable blockable, boolean reportSpam) { diff --git a/src/main/java/eu/siacs/conversations/utils/ReplacingSerialSingleThreadExecutor.java b/src/main/java/eu/siacs/conversations/utils/ReplacingSerialSingleThreadExecutor.java index dc8a0a825..0e97ef639 100644 --- a/src/main/java/eu/siacs/conversations/utils/ReplacingSerialSingleThreadExecutor.java +++ b/src/main/java/eu/siacs/conversations/utils/ReplacingSerialSingleThreadExecutor.java @@ -3,7 +3,7 @@ package eu.siacs.conversations.utils; public class ReplacingSerialSingleThreadExecutor extends SerialSingleThreadExecutor { public ReplacingSerialSingleThreadExecutor(boolean prepareLooper) { - super(prepareLooper); + super(ReplacingSerialSingleThreadExecutor.class.getName(), prepareLooper); } @Override diff --git a/src/main/java/eu/siacs/conversations/utils/SerialSingleThreadExecutor.java b/src/main/java/eu/siacs/conversations/utils/SerialSingleThreadExecutor.java index 79859af25..8c8b03f1a 100644 --- a/src/main/java/eu/siacs/conversations/utils/SerialSingleThreadExecutor.java +++ b/src/main/java/eu/siacs/conversations/utils/SerialSingleThreadExecutor.java @@ -1,12 +1,14 @@ package eu.siacs.conversations.utils; import android.os.Looper; +import android.util.Log; import java.util.ArrayDeque; import java.util.Queue; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import eu.siacs.conversations.Config; import eu.siacs.conversations.services.AttachFileToConversationRunnable; public class SerialSingleThreadExecutor implements Executor { @@ -14,12 +16,13 @@ public class SerialSingleThreadExecutor implements Executor { final Executor executor = Executors.newSingleThreadExecutor(); protected final ArrayDeque tasks = new ArrayDeque<>(); private Runnable active; + private final String name; - public SerialSingleThreadExecutor() { - this(false); + public SerialSingleThreadExecutor(String name) { + this(name, false); } - public SerialSingleThreadExecutor(boolean prepareLooper) { + public SerialSingleThreadExecutor(String name, boolean prepareLooper) { if (prepareLooper) { execute(new Runnable() { @Override @@ -28,6 +31,7 @@ public class SerialSingleThreadExecutor implements Executor { } }); } + this.name = name; } public synchronized void execute(final Runnable r) { @@ -48,6 +52,10 @@ public class SerialSingleThreadExecutor implements Executor { protected synchronized void scheduleNext() { if ((active = tasks.poll()) != null) { executor.execute(active); + int remaining = tasks.size(); + if (remaining > 0) { + Log.d(Config.LOGTAG,remaining+" remaining tasks on executor '"+name+"'"); + } } } } \ No newline at end of file