excute db read and writes on different threads

This commit is contained in:
Daniel Gultsch 2017-11-16 15:53:03 +01:00
parent 3dbe5db44b
commit 013822fe82
5 changed files with 28 additions and 19 deletions

View File

@ -276,7 +276,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
this.messageCache = new HashMap<>(); this.messageCache = new HashMap<>();
this.sessions = new SessionMap(mXmppConnectionService, axolotlStore, account); this.sessions = new SessionMap(mXmppConnectionService, axolotlStore, account);
this.fetchStatusMap = new FetchStatusMap(); this.fetchStatusMap = new FetchStatusMap();
this.executor = new SerialSingleThreadExecutor(); this.executor = new SerialSingleThreadExecutor("Axolotl");
} }
public String getOwnFingerprint() { public String getOwnFingerprint() {

View File

@ -762,7 +762,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
public boolean setNextMessage(String message) { public boolean setNextMessage(String message) {
boolean changed = !getNextMessage().equals(message); boolean changed = !getNextMessage().equals(message);
this.setAttribute(ATTRIBUTE_NEXT_MESSAGE,message); this.setAttribute(ATTRIBUTE_NEXT_MESSAGE, message);
return changed; return changed;
} }
@ -851,7 +851,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
public boolean setAttribute(String key, String value) { public boolean setAttribute(String key, String value) {
synchronized (this.attributes) { synchronized (this.attributes) {
try { try {
this.attributes.put(key, value); this.attributes.put(key, value == null ? "" : value);
return true; return true;
} catch (JSONException e) { } catch (JSONException e) {
return false; return false;

View File

@ -155,9 +155,10 @@ public class XmppConnectionService extends Service {
private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts"; 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_TOKEN_REFRESH = "gcm_token_refresh";
public static final String ACTION_GCM_MESSAGE_RECEIVED = "gcm_message_received"; public static final String ACTION_GCM_MESSAGE_RECEIVED = "gcm_message_received";
private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor(); private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor("FileAdding");
private final SerialSingleThreadExecutor mVideoCompressionExecutor = new SerialSingleThreadExecutor(); private final SerialSingleThreadExecutor mVideoCompressionExecutor = new SerialSingleThreadExecutor("VideoCompression");
private final SerialSingleThreadExecutor mDatabaseExecutor = new SerialSingleThreadExecutor(); private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter");
private final SerialSingleThreadExecutor mDatabaseReaderExecutor = new SerialSingleThreadExecutor("DatabaseReader");
private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor(true); private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor(true);
private final IBinder mBinder = new XmppConnectionBinder(); private final IBinder mBinder = new XmppConnectionBinder();
private final List<Conversation> conversations = new CopyOnWriteArrayList<>(); private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
@ -874,7 +875,7 @@ public class XmppConnectionService extends Service {
public void expireOldMessages(final boolean resetHasMessagesLeftOnServer) { public void expireOldMessages(final boolean resetHasMessagesLeftOnServer) {
mLastExpiryRun.set(SystemClock.elapsedRealtime()); mLastExpiryRun.set(SystemClock.elapsedRealtime());
mDatabaseExecutor.execute(new Runnable() { mDatabaseWriterExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
long timestamp = getAutomaticMessageDeletionDate(); long timestamp = getAutomaticMessageDeletionDate();
@ -1450,7 +1451,7 @@ public class XmppConnectionService extends Service {
updateConversationUi(); 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<Account> getAccounts() { public List<Account> getAccounts() {
@ -1715,7 +1716,7 @@ public class XmppConnectionService extends Service {
} }
}; };
if (async) { if (async) {
mDatabaseExecutor.execute(runnable); mDatabaseReaderExecutor.execute(runnable);
} else { } else {
runnable.run(); runnable.run();
} }
@ -1892,7 +1893,7 @@ public class XmppConnectionService extends Service {
} }
} }
}; };
mDatabaseExecutor.execute(runnable); mDatabaseWriterExecutor.execute(runnable);
this.accounts.remove(account); this.accounts.remove(account);
updateAccountUi(); updateAccountUi();
getNotificationService().updateErrorNotification(); getNotificationService().updateErrorNotification();
@ -3082,7 +3083,7 @@ public class XmppConnectionService extends Service {
} }
public void updateConversation(final Conversation conversation) { public void updateConversation(final Conversation conversation) {
mDatabaseExecutor.execute(new Runnable() { mDatabaseWriterExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
databaseBackend.updateConversation(conversation); databaseBackend.updateConversation(conversation);
@ -3364,7 +3365,7 @@ public class XmppConnectionService extends Service {
} }
} }
}; };
mDatabaseExecutor.execute(runnable); mDatabaseWriterExecutor.execute(runnable);
updateUnreadCountBadge(); updateUnreadCountBadge();
return true; return true;
} else { } else {
@ -3441,7 +3442,7 @@ public class XmppConnectionService extends Service {
databaseBackend.writeRoster(account.getRoster()); databaseBackend.writeRoster(account.getRoster());
} }
}; };
mDatabaseExecutor.execute(runnable); mDatabaseWriterExecutor.execute(runnable);
} }
@ -3662,7 +3663,7 @@ public class XmppConnectionService extends Service {
databaseBackend.updateConversation(conversation); databaseBackend.updateConversation(conversation);
} }
}; };
mDatabaseExecutor.execute(runnable); mDatabaseWriterExecutor.execute(runnable);
} }
public boolean sendBlockRequest(final Blockable blockable, boolean reportSpam) { public boolean sendBlockRequest(final Blockable blockable, boolean reportSpam) {

View File

@ -3,7 +3,7 @@ package eu.siacs.conversations.utils;
public class ReplacingSerialSingleThreadExecutor extends SerialSingleThreadExecutor { public class ReplacingSerialSingleThreadExecutor extends SerialSingleThreadExecutor {
public ReplacingSerialSingleThreadExecutor(boolean prepareLooper) { public ReplacingSerialSingleThreadExecutor(boolean prepareLooper) {
super(prepareLooper); super(ReplacingSerialSingleThreadExecutor.class.getName(), prepareLooper);
} }
@Override @Override

View File

@ -1,12 +1,14 @@
package eu.siacs.conversations.utils; package eu.siacs.conversations.utils;
import android.os.Looper; import android.os.Looper;
import android.util.Log;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.services.AttachFileToConversationRunnable; import eu.siacs.conversations.services.AttachFileToConversationRunnable;
public class SerialSingleThreadExecutor implements Executor { public class SerialSingleThreadExecutor implements Executor {
@ -14,12 +16,13 @@ public class SerialSingleThreadExecutor implements Executor {
final Executor executor = Executors.newSingleThreadExecutor(); final Executor executor = Executors.newSingleThreadExecutor();
protected final ArrayDeque<Runnable> tasks = new ArrayDeque<>(); protected final ArrayDeque<Runnable> tasks = new ArrayDeque<>();
private Runnable active; private Runnable active;
private final String name;
public SerialSingleThreadExecutor() { public SerialSingleThreadExecutor(String name) {
this(false); this(name, false);
} }
public SerialSingleThreadExecutor(boolean prepareLooper) { public SerialSingleThreadExecutor(String name, boolean prepareLooper) {
if (prepareLooper) { if (prepareLooper) {
execute(new Runnable() { execute(new Runnable() {
@Override @Override
@ -28,6 +31,7 @@ public class SerialSingleThreadExecutor implements Executor {
} }
}); });
} }
this.name = name;
} }
public synchronized void execute(final Runnable r) { public synchronized void execute(final Runnable r) {
@ -48,6 +52,10 @@ public class SerialSingleThreadExecutor implements Executor {
protected synchronized void scheduleNext() { protected synchronized void scheduleNext() {
if ((active = tasks.poll()) != null) { if ((active = tasks.poll()) != null) {
executor.execute(active); executor.execute(active);
int remaining = tasks.size();
if (remaining > 0) {
Log.d(Config.LOGTAG,remaining+" remaining tasks on executor '"+name+"'");
}
} }
} }
} }