mirror of https://github.com/M66B/FairEmail.git
Simplify store keep alive
This commit is contained in:
parent
0bf88fcf9e
commit
ee4339a971
|
@ -337,10 +337,61 @@ public class FragmentFolder extends FragmentEx {
|
||||||
pbWait.setVisibility(View.GONE);
|
pbWait.setVisibility(View.GONE);
|
||||||
Helper.setViewsEnabled(view, true);
|
Helper.setViewsEnabled(view, true);
|
||||||
etRename.setEnabled(folder == null || EntityFolder.USER.equals(folder.type));
|
etRename.setEnabled(folder == null || EntityFolder.USER.equals(folder.type));
|
||||||
grpInterval.setVisibility(folder == null || EntityFolder.USER.equals(folder.type) ? View.VISIBLE : View.GONE);
|
|
||||||
btnSave.setEnabled(true);
|
btnSave.setEnabled(true);
|
||||||
ibDelete.setVisibility(folder == null || !EntityFolder.USER.equals(folder.type) ? View.GONE : View.VISIBLE);
|
ibDelete.setVisibility(folder == null || !EntityFolder.USER.equals(folder.type) ? View.GONE : View.VISIBLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putLong("id", id);
|
||||||
|
args.putLong("account", account);
|
||||||
|
|
||||||
|
new SimpleTask<Boolean>() {
|
||||||
|
@Override
|
||||||
|
protected Boolean onLoad(Context context, Bundle args) throws Throwable {
|
||||||
|
long fid = args.getLong("id");
|
||||||
|
long aid = args.getLong("account");
|
||||||
|
|
||||||
|
IMAPStore istore = null;
|
||||||
|
DB db = DB.getInstance(getContext());
|
||||||
|
try {
|
||||||
|
db.beginTransaction();
|
||||||
|
|
||||||
|
EntityAccount account;
|
||||||
|
if (fid < 0)
|
||||||
|
account = db.account().getAccount(aid);
|
||||||
|
else {
|
||||||
|
EntityFolder folder = db.folder().getFolder(fid);
|
||||||
|
account = db.account().getAccount(folder.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
|
||||||
|
Properties props = MessageHelper.getSessionProperties(account.auth_type);
|
||||||
|
Session isession = Session.getInstance(props, null);
|
||||||
|
istore = (IMAPStore) isession.getStore("imaps");
|
||||||
|
istore.connect(account.host, account.port, account.user, account.password);
|
||||||
|
|
||||||
|
return istore.hasCapability("IDLE");
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
|
||||||
|
if (istore != null)
|
||||||
|
istore.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLoaded(Bundle args, Boolean capIdle) {
|
||||||
|
grpInterval.setVisibility(capIdle ? View.GONE : View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onException(Bundle args, Throwable ex) {
|
||||||
|
grpInterval.setVisibility(View.VISIBLE);
|
||||||
|
if (BuildConfig.DEBUG)
|
||||||
|
Helper.unexpectedError(getContext(), ex);
|
||||||
|
}
|
||||||
|
}.load(this, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,12 +50,10 @@ import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.sun.mail.iap.ConnectionException;
|
import com.sun.mail.iap.ConnectionException;
|
||||||
import com.sun.mail.iap.ProtocolException;
|
|
||||||
import com.sun.mail.imap.AppendUID;
|
import com.sun.mail.imap.AppendUID;
|
||||||
import com.sun.mail.imap.IMAPFolder;
|
import com.sun.mail.imap.IMAPFolder;
|
||||||
import com.sun.mail.imap.IMAPMessage;
|
import com.sun.mail.imap.IMAPMessage;
|
||||||
import com.sun.mail.imap.IMAPStore;
|
import com.sun.mail.imap.IMAPStore;
|
||||||
import com.sun.mail.imap.protocol.IMAPProtocol;
|
|
||||||
import com.sun.mail.util.FolderClosedIOException;
|
import com.sun.mail.util.FolderClosedIOException;
|
||||||
import com.sun.mail.util.MailConnectException;
|
import com.sun.mail.util.MailConnectException;
|
||||||
|
|
||||||
|
@ -129,7 +127,6 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
|
|
||||||
private static final int CONNECT_BACKOFF_START = 8; // seconds
|
private static final int CONNECT_BACKOFF_START = 8; // seconds
|
||||||
private static final int CONNECT_BACKOFF_MAX = 1024; // seconds (1024 sec ~ 17 min)
|
private static final int CONNECT_BACKOFF_MAX = 1024; // seconds (1024 sec ~ 17 min)
|
||||||
private static final long STORE_NOOP_INTERVAL = 9 * 60 * 1000L; // milliseconds
|
|
||||||
private static final int SYNC_BATCH_SIZE = 20;
|
private static final int SYNC_BATCH_SIZE = 20;
|
||||||
private static final int DOWNLOAD_BATCH_SIZE = 20;
|
private static final int DOWNLOAD_BATCH_SIZE = 20;
|
||||||
private static final int MESSAGE_AUTO_DOWNLOAD_SIZE = 32 * 1024; // bytes
|
private static final int MESSAGE_AUTO_DOWNLOAD_SIZE = 32 * 1024; // bytes
|
||||||
|
@ -559,6 +556,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
boolean debug = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("debug", false);
|
boolean debug = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("debug", false);
|
||||||
|
debug = debug || BuildConfig.DEBUG;
|
||||||
System.setProperty("mail.socket.debug", Boolean.toString(debug));
|
System.setProperty("mail.socket.debug", Boolean.toString(debug));
|
||||||
|
|
||||||
// Create session
|
// Create session
|
||||||
|
@ -569,7 +567,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
|
|
||||||
final IMAPStore istore = (IMAPStore) isession.getStore("imaps");
|
final IMAPStore istore = (IMAPStore) isession.getStore("imaps");
|
||||||
final Map<EntityFolder, IMAPFolder> folders = new HashMap<>();
|
final Map<EntityFolder, IMAPFolder> folders = new HashMap<>();
|
||||||
List<Thread> noops = new ArrayList<>();
|
List<Thread> pollers = new ArrayList<>();
|
||||||
List<Thread> idlers = new ArrayList<>();
|
List<Thread> idlers = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
// Listen for store events
|
// Listen for store events
|
||||||
|
@ -672,7 +670,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
db.folder().setFolderError(folder.id, null);
|
db.folder().setFolderError(folder.id, null);
|
||||||
|
|
||||||
// Keep folder connection alive
|
// Keep folder connection alive
|
||||||
Thread noop = new Thread(new Runnable() {
|
Thread poller = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
@ -811,30 +809,15 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Log.i(Helper.TAG, folder.name + " start noop");
|
if (!capIdle) {
|
||||||
while (state.running && ifolder.isOpen()) {
|
Log.i(Helper.TAG, folder.name + " start polling");
|
||||||
try {
|
while (state.running) {
|
||||||
if (!EntityFolder.USER.equals(folder.type) && capIdle) {
|
try {
|
||||||
Thread.sleep(account.poll_interval * 60 * 1000L);
|
Thread.sleep((folder.poll_interval == null ? 9 : folder.poll_interval) * 60 * 1000L);
|
||||||
Log.i(Helper.TAG, folder.name + " request NOOP");
|
|
||||||
ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
|
|
||||||
public Object doCommand(IMAPProtocol p) throws ProtocolException {
|
|
||||||
Log.i(Helper.TAG, ifolder.getName() + " start NOOP");
|
|
||||||
p.simpleCommand("NOOP", null);
|
|
||||||
Log.i(Helper.TAG, ifolder.getName() + " end NOOP");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (folder.poll_interval == null)
|
|
||||||
Thread.sleep(account.poll_interval * 60 * 1000L);
|
|
||||||
else
|
|
||||||
Thread.sleep(folder.poll_interval * 60 * 1000L);
|
|
||||||
synchronizeMessages(account, folder, ifolder, state);
|
synchronizeMessages(account, folder, ifolder, state);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
Log.w(Helper.TAG, folder.name + " poll " + ex.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
Log.w(Helper.TAG, folder.name + " noop " + ex.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
|
@ -847,16 +830,17 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
state.notifyAll();
|
state.notifyAll();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Log.i(Helper.TAG, folder.name + " end noop");
|
if (!capIdle)
|
||||||
|
Log.i(Helper.TAG, folder.name + " end polling");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, "sync.noop." + folder.id);
|
}, "sync.poller." + folder.id);
|
||||||
noop.start();
|
poller.start();
|
||||||
noops.add(noop);
|
pollers.add(poller);
|
||||||
|
|
||||||
// Receive folder events
|
// Receive folder events
|
||||||
if (!EntityFolder.USER.equals(folder.type) && capIdle) {
|
if (capIdle) {
|
||||||
Thread idle = new Thread(new Runnable() {
|
Thread idler = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
@ -880,8 +864,8 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, "sync.idle." + folder.id);
|
}, "sync.idle." + folder.id);
|
||||||
idle.start();
|
idler.start();
|
||||||
idlers.add(idle);
|
idlers.add(idler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,22 +953,18 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Keep store alive
|
// Keep store alive
|
||||||
while (state.running && istore.isConnected()) {
|
while (state.running) {
|
||||||
Log.i(Helper.TAG, "Checking folders");
|
|
||||||
for (EntityFolder folder : folders.keySet())
|
|
||||||
if (!folders.get(folder).isOpen())
|
|
||||||
throw new FolderClosedException(folders.get(folder));
|
|
||||||
|
|
||||||
// Wait for stop or folder error
|
|
||||||
Log.i(Helper.TAG, account.name + " wait");
|
Log.i(Helper.TAG, account.name + " wait");
|
||||||
synchronized (state) {
|
synchronized (state) {
|
||||||
try {
|
try {
|
||||||
state.wait(STORE_NOOP_INTERVAL);
|
state.wait(account.poll_interval * 60 * 1000L);
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
Log.w(Helper.TAG, account.name + " wait " + ex.toString());
|
Log.w(Helper.TAG, account.name + " wait " + ex.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.i(Helper.TAG, account.name + " waited");
|
|
||||||
|
if (!istore.isConnected())
|
||||||
|
throw new StoreClosedException(istore);
|
||||||
}
|
}
|
||||||
Log.i(Helper.TAG, account.name + " done running=" + state.running);
|
Log.i(Helper.TAG, account.name + " done running=" + state.running);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -996,11 +976,18 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
|
|
||||||
db.account().setAccountError(account.id, Helper.formatThrowable(ex));
|
db.account().setAccountError(account.id, Helper.formatThrowable(ex));
|
||||||
} finally {
|
} finally {
|
||||||
// Close store
|
|
||||||
EntityLog.log(this, account.name + " closing");
|
EntityLog.log(this, account.name + " closing");
|
||||||
db.account().setAccountState(account.id, "closing");
|
db.account().setAccountState(account.id, "closing");
|
||||||
for (EntityFolder folder : folders.keySet())
|
for (EntityFolder folder : folders.keySet())
|
||||||
db.folder().setFolderState(folder.id, "closing");
|
db.folder().setFolderState(folder.id, "closing");
|
||||||
|
|
||||||
|
// Stop pollers
|
||||||
|
for (Thread poller : pollers) {
|
||||||
|
poller.interrupt();
|
||||||
|
join(poller);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close store
|
||||||
try {
|
try {
|
||||||
Thread t = new Thread(new Runnable() {
|
Thread t = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -1030,16 +1017,10 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
db.folder().setFolderState(folder.id, null);
|
db.folder().setFolderState(folder.id, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop noop
|
// Stop idlers
|
||||||
for (Thread noop : noops) {
|
for (Thread idler : idlers) {
|
||||||
noop.interrupt();
|
idler.interrupt();
|
||||||
join(noop);
|
join(idler);
|
||||||
}
|
|
||||||
|
|
||||||
// Stop idle
|
|
||||||
for (Thread idle : idlers) {
|
|
||||||
idle.interrupt();
|
|
||||||
join(idle);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1541,10 +1522,12 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
if (message == null)
|
if (message == null)
|
||||||
full.add(imessage);
|
full.add(imessage);
|
||||||
}
|
}
|
||||||
long headers = SystemClock.elapsedRealtime();
|
if (full.size() > 0) {
|
||||||
ifolder.fetch(full.toArray(new Message[0]), fp);
|
long headers = SystemClock.elapsedRealtime();
|
||||||
Log.i(Helper.TAG, folder.name + " fetched headers=" + full.size() +
|
ifolder.fetch(full.toArray(new Message[0]), fp);
|
||||||
" " + (SystemClock.elapsedRealtime() - headers) + " ms");
|
Log.i(Helper.TAG, folder.name + " fetched headers=" + full.size() +
|
||||||
|
" " + (SystemClock.elapsedRealtime() - headers) + " ms");
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = isub.length - 1; j >= 0; j--)
|
for (int j = isub.length - 1; j >= 0; j--)
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue