mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-30 13:12:25 -05:00
Handle aborted imap searches by nuking in-progress connections.
This commit is contained in:
parent
9f96cd36a7
commit
2541753aff
@ -8,6 +8,7 @@ import java.util.EnumMap;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
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.Flag;
|
||||||
import com.fsck.k9.mail.Folder;
|
import com.fsck.k9.mail.Folder;
|
||||||
import com.fsck.k9.mail.Message;
|
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;
|
||||||
import com.fsck.k9.mail.store.LocalStore.LocalFolder;
|
import com.fsck.k9.mail.store.LocalStore.LocalFolder;
|
||||||
import com.fsck.k9.mail.store.StorageManager;
|
import com.fsck.k9.mail.store.StorageManager;
|
||||||
@ -300,6 +303,7 @@ public class MessageList extends K9ListActivity implements OnItemClickListener {
|
|||||||
private boolean mRemoteSearch = false;
|
private boolean mRemoteSearch = false;
|
||||||
private String mSearchAccount = null;
|
private String mSearchAccount = null;
|
||||||
private String mSearchFolder = null;
|
private String mSearchFolder = null;
|
||||||
|
private Future mRemoteSearchFuture = null;
|
||||||
private boolean mIntegrate = false;
|
private boolean mIntegrate = false;
|
||||||
private String[] mAccountUuids = null;
|
private String[] mAccountUuids = null;
|
||||||
private String[] mFolderNames = null;
|
private String[] mFolderNames = null;
|
||||||
@ -983,7 +987,7 @@ public class MessageList extends K9ListActivity implements OnItemClickListener {
|
|||||||
if (mAdapter.isEmpty()) {
|
if (mAdapter.isEmpty()) {
|
||||||
if (mRemoteSearch) {
|
if (mRemoteSearch) {
|
||||||
//TODO: Support flag based search
|
//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) {
|
} else if (mFolderName != null) {
|
||||||
mController.listLocalMessages(mAccount, mFolderName, mAdapter.mListener);
|
mController.listLocalMessages(mAccount, mFolderName, mAdapter.mListener);
|
||||||
// Hide the archive button if we don't have an archive folder.
|
// 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);
|
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
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
int itemId = item.getItemId();
|
int itemId = item.getItemId();
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
package com.fsck.k9.controller;
|
package com.fsck.k9.controller;
|
||||||
|
|
||||||
import java.io.CharArrayWriter;
|
import java.io.CharArrayWriter;
|
||||||
@ -16,13 +15,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.*;
|
||||||
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.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
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) {
|
if (K9.DEBUG) {
|
||||||
String msg = "searchRemoteMessages ("
|
String msg = "searchRemoteMessages ("
|
||||||
+ "acct=" + acctUuid
|
+ "acct=" + acctUuid
|
||||||
@ -800,7 +793,7 @@ public class MessagingController implements Runnable {
|
|||||||
Log.i(K9.LOG_TAG, msg);
|
Log.i(K9.LOG_TAG, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
threadPool.execute(new Runnable() {
|
return threadPool.submit(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
searchRemoteMessagesSynchronous(acctUuid, folderName, query, requiredFlags, forbiddenFlags, listener);
|
searchRemoteMessagesSynchronous(acctUuid, folderName, query, requiredFlags, forbiddenFlags, listener);
|
||||||
@ -852,11 +845,15 @@ public class MessagingController implements Runnable {
|
|||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(K9.LOG_TAG, "Could not complete remote search", e);
|
if (Thread.currentThread().isInterrupted()) {
|
||||||
if (listener != null) {
|
Log.i(K9.LOG_TAG, "Caught exception on aborted remote search; safe to ignore.", e);
|
||||||
listener.remoteSearchFailed(acct, null, e.getMessage());
|
} 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 {
|
} finally {
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.remoteSearchFinished(acct, folderName, 0, extraResults);
|
listener.remoteSearchFinished(acct, folderName, 0, extraResults);
|
||||||
|
@ -820,7 +820,7 @@ public class ImapStore extends Store {
|
|||||||
private volatile boolean mExists;
|
private volatile boolean mExists;
|
||||||
private ImapStore store = null;
|
private ImapStore store = null;
|
||||||
Map<Long, String> msgSeqUidMap = new ConcurrentHashMap<Long, String>();
|
Map<Long, String> msgSeqUidMap = new ConcurrentHashMap<Long, String>();
|
||||||
|
private boolean mInSearch = false;
|
||||||
|
|
||||||
public ImapFolder(ImapStore nStore, String name) {
|
public ImapFolder(ImapStore nStore, String name) {
|
||||||
super(nStore.getAccount());
|
super(nStore.getAccount());
|
||||||
@ -1000,7 +1000,13 @@ public class ImapStore extends Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (this) {
|
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;
|
mConnection = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2307,11 +2313,11 @@ public class ImapStore extends Store {
|
|||||||
open(OpenMode.READ_ONLY);
|
open(OpenMode.READ_ONLY);
|
||||||
checkOpen();
|
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);
|
return search(searcher, null);
|
||||||
} catch (Exception e) {
|
} finally {
|
||||||
Log.e(K9.LOG_TAG, "Exception caught during remote search", e);
|
mInSearch = false;
|
||||||
throw new MessagingException("Error during search: " + e.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user