1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-30 13:12:25 -05:00

svn merge -x -w -c 760 ../issue4-1.X/ .

Improve reliability of message viewing and composing while still using
MessagingController worker queues

svn merge -x -w -c 761 ../issue4-1.X/ .

Put loading a message from the LocalStore into a ThreadPool executor,
like was done previously in MessageView.  Remote loading still goes
through the work queue.
This commit is contained in:
Daniel Applebaum 2009-09-17 03:43:02 +00:00
parent 5d5c65bee3
commit 08cd19e5a8
2 changed files with 46 additions and 30 deletions

View File

@ -15,6 +15,8 @@ import java.util.Set;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -106,6 +108,8 @@ public class MessagingController implements Runnable {
private ConcurrentHashMap<String, AtomicInteger> sendCount = new ConcurrentHashMap<String, AtomicInteger>(); private ConcurrentHashMap<String, AtomicInteger> sendCount = new ConcurrentHashMap<String, AtomicInteger>();
private final ExecutorService threadPool = Executors.newFixedThreadPool(3);
public enum SORT_TYPE { public enum SORT_TYPE {
SORT_DATE(R.string.sort_earliest_first, R.string.sort_latest_first, false), SORT_DATE(R.string.sort_earliest_first, R.string.sort_latest_first, false),
SORT_SUBJECT(R.string.sort_subject_alpha, R.string.sort_subject_re_alpha, true), SORT_SUBJECT(R.string.sort_subject_alpha, R.string.sort_subject_re_alpha, true),
@ -287,10 +291,10 @@ public class MessagingController implements Runnable {
if (command != null) { if (command != null) {
commandDescription = command.description; commandDescription = command.description;
Log.d(Email.LOG_TAG, "Running background command '" + command.description + "'"); Log.i(Email.LOG_TAG, "Running background command '" + command.description + "'");
mBusy = true; mBusy = true;
command.runnable.run(); command.runnable.run();
Log.d(Email.LOG_TAG, "Background command '" + command.description + "' completed"); Log.i(Email.LOG_TAG, "Background command '" + command.description + "' completed");
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.controllerCommandCompleted(mCommands.size() > 0); l.controllerCommandCompleted(mCommands.size() > 0);
} }
@ -307,25 +311,20 @@ public class MessagingController implements Runnable {
} }
private void put(String description, MessagingListener listener, Runnable runnable) { private void put(String description, MessagingListener listener, Runnable runnable) {
try { putCommand(mCommands, description, listener, runnable);
Command command = new Command();
command.listener = listener;
command.runnable = runnable;
command.description = description;
mCommands.put(command);
} }
catch (InterruptedException ie) {
throw new Error(ie);
}
}
private void putBackground(String description, MessagingListener listener, Runnable runnable) { private void putBackground(String description, MessagingListener listener, Runnable runnable) {
putCommand(backCommands, description, listener, runnable);
}
private void putCommand(BlockingQueue<Command> queue, String description, MessagingListener listener, Runnable runnable) {
try { try {
Command command = new Command(); Command command = new Command();
command.listener = listener; command.listener = listener;
command.runnable = runnable; command.runnable = runnable;
command.description = description; command.description = description;
backCommands.put(command); queue.put(command);
} }
catch (InterruptedException ie) { catch (InterruptedException ie) {
throw new Error(ie); throw new Error(ie);
@ -1797,14 +1796,14 @@ public class MessagingController implements Runnable {
markMessageRead(account, localFolder, message, true); markMessageRead(account, localFolder, message, true);
} }
if (listener != null) if (listener != null && !getListeners().contains(listener))
{ {
listener.loadMessageForViewBodyAvailable(account, folder, uid, message); listener.loadMessageForViewBodyAvailable(account, folder, uid, message);
} }
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.loadMessageForViewBodyAvailable(account, folder, uid, message); l.loadMessageForViewBodyAvailable(account, folder, uid, message);
} }
if (listener != null) if (listener != null && !getListeners().contains(listener))
{ {
listener.loadMessageForViewFinished(account, folder, uid, message); listener.loadMessageForViewFinished(account, folder, uid, message);
} }
@ -1816,6 +1815,10 @@ public class MessagingController implements Runnable {
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.loadMessageForViewFailed(account, folder, uid, e.getMessage()); l.loadMessageForViewFailed(account, folder, uid, e.getMessage());
} }
if (listener != null && !getListeners().contains(listener))
{
listener.loadMessageForViewFailed(account, folder, uid, e.getMessage());
}
addErrorMessage(account, e); addErrorMessage(account, e);
} }
@ -1843,10 +1846,17 @@ public class MessagingController implements Runnable {
} }
public void loadMessageForView(final Account account, final String folder, final String uid, public void loadMessageForView(final Account account, final String folder, final String uid,
MessagingListener listener) { final MessagingListener listener) {
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.loadMessageForViewStarted(account, folder, uid); l.loadMessageForViewStarted(account, folder, uid);
} }
if (listener != null && !getListeners().contains(listener))
{
listener.loadMessageForViewStarted(account, folder, uid);
}
threadPool.execute(new Runnable() {
public void run() {
try { try {
Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication); Store localStore = Store.getInstance(account.getLocalStoreUri(), mApplication);
LocalFolder localFolder = (LocalFolder) localStore.getFolder(folder); LocalFolder localFolder = (LocalFolder) localStore.getFolder(folder);
@ -1857,7 +1867,7 @@ public class MessagingController implements Runnable {
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.loadMessageForViewHeadersAvailable(account, folder, uid, message); l.loadMessageForViewHeadersAvailable(account, folder, uid, message);
} }
if (listener != null) if (listener != null && !getListeners().contains(listener))
{ {
listener.loadMessageForViewHeadersAvailable(account, folder, uid, message); listener.loadMessageForViewHeadersAvailable(account, folder, uid, message);
} }
@ -1874,7 +1884,7 @@ public class MessagingController implements Runnable {
localFolder.fetch(new Message[] { localFolder.fetch(new Message[] {
message message
}, fp, null); }, fp, null);
localFolder.close(false);
if (!message.isSet(Flag.SEEN)) { if (!message.isSet(Flag.SEEN)) {
markMessageRead(account, localFolder, message, true); markMessageRead(account, localFolder, message, true);
} }
@ -1882,7 +1892,7 @@ public class MessagingController implements Runnable {
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.loadMessageForViewBodyAvailable(account, folder, uid, message); l.loadMessageForViewBodyAvailable(account, folder, uid, message);
} }
if (listener != null) if (listener != null && !getListeners().contains(listener))
{ {
listener.loadMessageForViewBodyAvailable(account, folder, uid, message); listener.loadMessageForViewBodyAvailable(account, folder, uid, message);
} }
@ -1890,19 +1900,25 @@ public class MessagingController implements Runnable {
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.loadMessageForViewFinished(account, folder, uid, message); l.loadMessageForViewFinished(account, folder, uid, message);
} }
if (listener != null) if (listener != null && !getListeners().contains(listener))
{ {
listener.loadMessageForViewFinished(account, folder, uid, message); listener.loadMessageForViewFinished(account, folder, uid, message);
} }
localFolder.close(false);
} }
catch (Exception e) { catch (Exception e) {
for (MessagingListener l : getListeners()) { for (MessagingListener l : getListeners()) {
l.loadMessageForViewFailed(account, folder, uid, e.getMessage()); l.loadMessageForViewFailed(account, folder, uid, e.getMessage());
} }
if (listener != null && !getListeners().contains(listener))
{
listener.loadMessageForViewFailed(account, folder, uid, e.getMessage());
}
addErrorMessage(account, e); addErrorMessage(account, e);
} }
}
});
} }
// public void loadMessageForViewSynchronous(final Account account, final String folder, final String uid, // public void loadMessageForViewSynchronous(final Account account, final String folder, final String uid,

View File

@ -500,14 +500,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
updateFrom(); updateFrom();
updateSignature(); updateSignature();
Log.d(Email.LOG_TAG, "action = " + action + ", mAccount = " + mAccount + ", mFolder = " + mFolder + ", mSourceMessageUid = " + mSourceMessageUid);
if ((ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) && mAccount != null && mFolder != null && mSourceMessageUid != null) {
Log.d(Email.LOG_TAG, "Setting message ANSWERED flag to true");
// TODO: Really, we should wait until we send the message, but that would require saving the original
// message info along with a Draft copy, in case it is left in Drafts for a while before being sent
MessagingController.getInstance(getApplication()).setMessageFlag(mAccount, mFolder, mSourceMessageUid, Flag.ANSWERED, true);
}
if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action) || ACTION_FORWARD.equals(action) || ACTION_EDIT_DRAFT.equals(action)) { if (ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action) || ACTION_FORWARD.equals(action) || ACTION_EDIT_DRAFT.equals(action)) {
/* /*
* If we need to load the message we add ourself as a message listener here * If we need to load the message we add ourself as a message listener here
@ -527,6 +519,14 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
addAddress(mBccView, new Address(mAccount.getAlwaysBcc(), "")); addAddress(mBccView, new Address(mAccount.getAlwaysBcc(), ""));
} }
Log.d(Email.LOG_TAG, "action = " + action + ", mAccount = " + mAccount + ", mFolder = " + mFolder + ", mSourceMessageUid = " + mSourceMessageUid);
if ((ACTION_REPLY.equals(action) || ACTION_REPLY_ALL.equals(action)) && mAccount != null && mFolder != null && mSourceMessageUid != null) {
Log.d(Email.LOG_TAG, "Setting message ANSWERED flag to true");
// TODO: Really, we should wait until we send the message, but that would require saving the original
// message info along with a Draft copy, in case it is left in Drafts for a while before being sent
MessagingController.getInstance(getApplication()).setMessageFlag(mAccount, mFolder, mSourceMessageUid, Flag.ANSWERED, true);
}
updateTitle(); updateTitle();
} }