Handle aborted imap searches by nuking in-progress connections.

This commit is contained in:
Andrew Chen 2012-09-25 15:46:30 -07:00
parent 9f96cd36a7
commit 2541753aff
3 changed files with 58 additions and 21 deletions

View File

@ -8,6 +8,7 @@ import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import android.app.AlertDialog;
import android.app.Dialog;
@ -72,6 +73,8 @@ import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Folder;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.Store;
import com.fsck.k9.mail.store.ImapStore;
import com.fsck.k9.mail.store.LocalStore;
import com.fsck.k9.mail.store.LocalStore.LocalFolder;
import com.fsck.k9.mail.store.StorageManager;
@ -300,6 +303,7 @@ public class MessageList extends K9ListActivity implements OnItemClickListener {
private boolean mRemoteSearch = false;
private String mSearchAccount = null;
private String mSearchFolder = null;
private Future mRemoteSearchFuture = null;
private boolean mIntegrate = false;
private String[] mAccountUuids = null;
private String[] mFolderNames = null;
@ -983,7 +987,7 @@ public class MessageList extends K9ListActivity implements OnItemClickListener {
if (mAdapter.isEmpty()) {
if (mRemoteSearch) {
//TODO: Support flag based search
mController.searchRemoteMessages(mSearchAccount, mSearchFolder, mQueryString, null, null, mAdapter.mListener);
mRemoteSearchFuture = mController.searchRemoteMessages(mSearchAccount, mSearchFolder, mQueryString, null, null, mAdapter.mListener);
} else if (mFolderName != null) {
mController.listLocalMessages(mAccount, mFolderName, mAdapter.mListener);
// Hide the archive button if we don't have an archive folder.
@ -1585,6 +1589,36 @@ public class MessageList extends K9ListActivity implements OnItemClickListener {
mController.sendPendingMessages(account, mAdapter.mListener);
}
/**
* We need to do some special clean up when leaving a remote search result screen. If no remote search is
* in progress, this method does nothing special.
*/
@Override
public void onBackPressed() {
// If we represent a remote search, then kill that before going back.
if(mSearchAccount != null && mSearchFolder != null && mRemoteSearchFuture != null) {
try {
Log.i(K9.LOG_TAG, "Remote search in progress, attempting to abort...");
// Canceling the future stops any message fetches in progress.
final boolean cancelSuccess = mRemoteSearchFuture.cancel(true); // mayInterruptIfRunning = true
if (!cancelSuccess) {
Log.e(K9.LOG_TAG, "Could not cancel remote search future.");
}
// Closing the folder will kill off the connection if we're mid-search.
final Account searchAccount = Preferences.getPreferences(this).getAccount(mSearchAccount);
final Store remoteStore = searchAccount.getRemoteStore();
final Folder remoteFolder = remoteStore.getFolder(mSearchFolder);
remoteFolder.close();
// Send a remoteSearchFinished() message for good measure.
mAdapter.mListener.remoteSearchFinished(searchAccount, mSearchFolder, 0, null);
} catch (Exception e) {
// Since the user is going back, log and squash any exceptions.
Log.e(K9.LOG_TAG, "Could not abort remote search before going back", e);
}
}
super.onBackPressed();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();

View File

@ -1,4 +1,3 @@
package com.fsck.k9.controller;
import java.io.CharArrayWriter;
@ -16,13 +15,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -790,7 +783,7 @@ public class MessagingController implements Runnable {
public void searchRemoteMessages(final String acctUuid, final String folderName, final String query, final Flag[] requiredFlags, final Flag[] forbiddenFlags, final MessagingListener listener) {
public Future searchRemoteMessages(final String acctUuid, final String folderName, final String query, final Flag[] requiredFlags, final Flag[] forbiddenFlags, final MessagingListener listener) {
if (K9.DEBUG) {
String msg = "searchRemoteMessages ("
+ "acct=" + acctUuid
@ -800,7 +793,7 @@ public class MessagingController implements Runnable {
Log.i(K9.LOG_TAG, msg);
}
threadPool.execute(new Runnable() {
return threadPool.submit(new Runnable() {
@Override
public void run() {
searchRemoteMessagesSynchronous(acctUuid, folderName, query, requiredFlags, forbiddenFlags, listener);
@ -852,11 +845,15 @@ public class MessagingController implements Runnable {
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Could not complete remote search", e);
if (listener != null) {
listener.remoteSearchFailed(acct, null, e.getMessage());
if (Thread.currentThread().isInterrupted()) {
Log.i(K9.LOG_TAG, "Caught exception on aborted remote search; safe to ignore.", e);
} else {
Log.e(K9.LOG_TAG, "Could not complete remote search", e);
if (listener != null) {
listener.remoteSearchFailed(acct, null, e.getMessage());
}
addErrorMessage(acct, null, e);
}
addErrorMessage(acct, null, e);
} finally {
if (listener != null) {
listener.remoteSearchFinished(acct, folderName, 0, extraResults);

View File

@ -820,7 +820,7 @@ public class ImapStore extends Store {
private volatile boolean mExists;
private ImapStore store = null;
Map<Long, String> msgSeqUidMap = new ConcurrentHashMap<Long, String>();
private boolean mInSearch = false;
public ImapFolder(ImapStore nStore, String name) {
super(nStore.getAccount());
@ -1000,7 +1000,13 @@ public class ImapStore extends Store {
}
synchronized (this) {
releaseConnection(mConnection);
// If we are mid-search and we get a close request, we gotta trash the connection.
if (mInSearch && mConnection != null) {
Log.i(K9.LOG_TAG, "IMAP search was aborted, shutting down connection.");
mConnection.close();
} else {
releaseConnection(mConnection);
}
mConnection = null;
}
}
@ -2307,11 +2313,11 @@ public class ImapStore extends Store {
open(OpenMode.READ_ONLY);
checkOpen();
//don't pass listener--we don't want to add messages until we've downloaded them
mInSearch = true;
// don't pass listener--we don't want to add messages until we've downloaded them
return search(searcher, null);
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Exception caught during remote search", e);
throw new MessagingException("Error during search: " + e.toString());
} finally {
mInSearch = false;
}
}