Skip errors for old sessions

This commit is contained in:
M66B 2020-09-21 08:12:45 +02:00
parent 42d938f32e
commit 99f5d25a99
3 changed files with 46 additions and 35 deletions

View File

@ -496,7 +496,8 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback<TupleMe
Log.i("Boundary server sync uid=" + uid); Log.i("Boundary server sync uid=" + uid);
EntityMessage message = db.message().getMessageByUid(browsable.id, uid); EntityMessage message = db.message().getMessageByUid(browsable.id, uid);
if (message == null) { if (message == null) {
message = Core.synchronizeMessage(context, message = Core.synchronizeMessage(
context, -1,
account, browsable, account, browsable,
(IMAPStore) state.iservice.getStore(), state.ifolder, (MimeMessage) isub[j], (IMAPStore) state.iservice.getStore(), state.ifolder, (MimeMessage) isub[j],
true, true, true, true,

View File

@ -147,7 +147,7 @@ class Core {
private static final int TOTAL_RETRY_MAX = LOCAL_RETRY_MAX * 10; private static final int TOTAL_RETRY_MAX = LOCAL_RETRY_MAX * 10;
static void processOperations( static void processOperations(
Context context, Context context, int session,
EntityAccount account, EntityFolder folder, List<TupleOperationEx> ops, EntityAccount account, EntityFolder folder, List<TupleOperationEx> ops,
Store istore, Folder ifolder, Store istore, Folder ifolder,
State state, int priority, long sequence) State state, int priority, long sequence)
@ -302,7 +302,7 @@ class Core {
break; break;
case EntityOperation.DELETE: case EntityOperation.DELETE:
onDelete(context, jargs, account, folder, message, (POP3Folder) ifolder, (POP3Store) istore, state); onDelete(context, session, jargs, account, folder, message, (POP3Folder) ifolder, (POP3Store) istore, state);
break; break;
case EntityOperation.SYNC: case EntityOperation.SYNC:
@ -341,22 +341,22 @@ class Core {
break; break;
case EntityOperation.ADD: case EntityOperation.ADD:
onAdd(context, jargs, account, folder, message, (IMAPStore) istore, (IMAPFolder) ifolder, state); onAdd(context, session, jargs, account, folder, message, (IMAPStore) istore, (IMAPFolder) ifolder, state);
break; break;
case EntityOperation.MOVE: case EntityOperation.MOVE:
List<EntityMessage> messages = new ArrayList<>(); List<EntityMessage> messages = new ArrayList<>();
messages.add(message); messages.add(message);
messages.addAll(similar.values()); messages.addAll(similar.values());
onMove(context, jargs, false, folder, messages, (IMAPStore) istore, (IMAPFolder) ifolder, state); onMove(context, session, jargs, false, folder, messages, (IMAPStore) istore, (IMAPFolder) ifolder, state);
break; break;
case EntityOperation.COPY: case EntityOperation.COPY:
onMove(context, jargs, true, folder, Arrays.asList(message), (IMAPStore) istore, (IMAPFolder) ifolder, state); onMove(context, session, jargs, true, folder, Arrays.asList(message), (IMAPStore) istore, (IMAPFolder) ifolder, state);
break; break;
case EntityOperation.FETCH: case EntityOperation.FETCH:
onFetch(context, jargs, folder, (IMAPStore) istore, (IMAPFolder) ifolder, state); onFetch(context, session, jargs, folder, (IMAPStore) istore, (IMAPFolder) ifolder, state);
break; break;
case EntityOperation.DELETE: case EntityOperation.DELETE:
@ -384,7 +384,7 @@ class Core {
break; break;
case EntityOperation.SYNC: case EntityOperation.SYNC:
onSynchronizeMessages(context, jargs, account, folder, (IMAPStore) istore, (IMAPFolder) ifolder, state); onSynchronizeMessages(context, session, jargs, account, folder, (IMAPStore) istore, (IMAPFolder) ifolder, state);
break; break;
case EntityOperation.SUBSCRIBE: case EntityOperation.SUBSCRIBE:
@ -797,7 +797,7 @@ class Core {
} }
} }
private static void onAdd(Context context, JSONArray jargs, EntityAccount account, EntityFolder folder, EntityMessage message, IMAPStore istore, IMAPFolder ifolder, State state) throws MessagingException, IOException { private static void onAdd(Context context, int session, JSONArray jargs, EntityAccount account, EntityFolder folder, EntityMessage message, IMAPStore istore, IMAPFolder ifolder, State state) throws MessagingException, IOException {
// Add message // Add message
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
@ -911,7 +911,7 @@ class Core {
try { try {
JSONArray fargs = new JSONArray(); JSONArray fargs = new JSONArray();
fargs.put(newuid); fargs.put(newuid);
onFetch(context, fargs, folder, istore, ifolder, state); onFetch(context, session, fargs, folder, istore, ifolder, state);
} catch (JSONException ex) { } catch (JSONException ex) {
Log.e(ex); Log.e(ex);
} }
@ -925,7 +925,7 @@ class Core {
} }
} }
private static void onMove(Context context, JSONArray jargs, boolean copy, EntityFolder folder, List<EntityMessage> messages, IMAPStore istore, IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException { private static void onMove(Context context, int session, JSONArray jargs, boolean copy, EntityFolder folder, List<EntityMessage> messages, IMAPStore istore, IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException {
// Move message // Move message
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
@ -1058,7 +1058,7 @@ class Core {
if (fetch) { if (fetch) {
JSONArray fargs = new JSONArray(); JSONArray fargs = new JSONArray();
fargs.put(uid); fargs.put(uid);
onFetch(context, fargs, target, istore, itarget, state); onFetch(context, session, fargs, target, istore, itarget, state);
} }
} }
} catch (Throwable ex) { } catch (Throwable ex) {
@ -1114,7 +1114,7 @@ class Core {
db.message().updateMessage(message); db.message().updateMessage(message);
} }
private static void onFetch(Context context, JSONArray jargs, EntityFolder folder, IMAPStore istore, IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException { private static void onFetch(Context context, int session, JSONArray jargs, EntityFolder folder, IMAPStore istore, IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException {
long uid = jargs.getLong(0); long uid = jargs.getLong(0);
boolean removed = jargs.optBoolean(1); boolean removed = jargs.optBoolean(1);
@ -1158,7 +1158,7 @@ class Core {
} }
ifolder.fetch(new Message[]{imessage}, fp); ifolder.fetch(new Message[]{imessage}, fp);
EntityMessage message = synchronizeMessage(context, account, folder, istore, ifolder, imessage, false, download, rules, state, stats); EntityMessage message = synchronizeMessage(context, session, account, folder, istore, ifolder, imessage, false, download, rules, state, stats);
if (message != null) { if (message != null) {
if (account.isGmail() && EntityFolder.USER.equals(folder.type)) if (account.isGmail() && EntityFolder.USER.equals(folder.type))
try { try {
@ -1171,7 +1171,7 @@ class Core {
} }
if (download) if (download)
downloadMessage(context, account, folder, istore, ifolder, imessage, message.id, state, stats); downloadMessage(context, session, account, folder, istore, ifolder, imessage, message.id, state, stats);
} }
if (!stats.isEmpty()) if (!stats.isEmpty())
@ -1247,7 +1247,7 @@ class Core {
} }
} }
private static void onDelete(Context context, JSONArray jargs, EntityAccount account, EntityFolder folder, EntityMessage message, POP3Folder ifolder, POP3Store istore, State state) throws MessagingException, IOException { private static void onDelete(Context context, int session, JSONArray jargs, EntityAccount account, EntityFolder folder, EntityMessage message, POP3Folder ifolder, POP3Store istore, State state) throws MessagingException, IOException {
// Delete message // Delete message
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
@ -1290,7 +1290,7 @@ class Core {
ifolder.open(Folder.READ_WRITE); ifolder.open(Folder.READ_WRITE);
} catch (Throwable ex) { } catch (Throwable ex) {
Log.e(ex); Log.e(ex);
state.error(new FolderClosedException(ifolder, "POP")); state.error(new FolderClosedException(ifolder, "POP"), session);
} }
} }
} }
@ -2087,7 +2087,7 @@ class Core {
} }
private static void onSynchronizeMessages( private static void onSynchronizeMessages(
Context context, JSONArray jargs, Context context, int session, JSONArray jargs,
EntityAccount account, final EntityFolder folder, EntityAccount account, final EntityFolder folder,
IMAPStore istore, final IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException { IMAPStore istore, final IMAPFolder ifolder, State state) throws JSONException, MessagingException, IOException {
final DB db = DB.getInstance(context); final DB db = DB.getInstance(context);
@ -2397,7 +2397,7 @@ class Core {
} }
EntityMessage message = synchronizeMessage( EntityMessage message = synchronizeMessage(
context, context, session,
account, folder, account, folder,
istore, ifolder, (MimeMessage) isub[j], istore, ifolder, (MimeMessage) isub[j],
false, download && initialize == 0, false, download && initialize == 0,
@ -2476,7 +2476,7 @@ class Core {
try { try {
if (ids[from + j] != null) { if (ids[from + j] != null) {
boolean fetched = downloadMessage( boolean fetched = downloadMessage(
context, context, session,
account, folder, account, folder,
istore, ifolder, istore, ifolder,
(MimeMessage) isub[j], ids[from + j], (MimeMessage) isub[j], ids[from + j],
@ -2532,7 +2532,7 @@ class Core {
} }
static EntityMessage synchronizeMessage( static EntityMessage synchronizeMessage(
Context context, Context context, int session,
EntityAccount account, EntityFolder folder, EntityAccount account, EntityFolder folder,
IMAPStore istore, IMAPFolder ifolder, MimeMessage imessage, IMAPStore istore, IMAPFolder ifolder, MimeMessage imessage,
boolean browsed, boolean download, boolean browsed, boolean download,
@ -2867,7 +2867,7 @@ class Core {
" size=" + message.size + "/" + (body == null ? null : body.length())); " size=" + message.size + "/" + (body == null ? null : body.length()));
if (TextUtils.isEmpty(body) && parts.hasBody()) if (TextUtils.isEmpty(body) && parts.hasBody())
reportEmptyMessage(context, state, account, istore); reportEmptyMessage(context, session, state, account, istore);
} }
} }
} else { } else {
@ -3188,7 +3188,7 @@ class Core {
} }
private static boolean downloadMessage( private static boolean downloadMessage(
Context context, Context context, int session,
EntityAccount account, EntityFolder folder, EntityAccount account, EntityFolder folder,
IMAPStore istore, IMAPFolder ifolder, IMAPStore istore, IMAPFolder ifolder,
MimeMessage imessage, long id, State state, SyncStats stats) throws MessagingException, IOException { MimeMessage imessage, long id, State state, SyncStats stats) throws MessagingException, IOException {
@ -3261,7 +3261,7 @@ class Core {
" size=" + message.size + "/" + (body == null ? null : body.length())); " size=" + message.size + "/" + (body == null ? null : body.length()));
if (TextUtils.isEmpty(body) && parts.hasBody()) if (TextUtils.isEmpty(body) && parts.hasBody())
reportEmptyMessage(context, state, account, istore); reportEmptyMessage(context, session, state, account, istore);
} }
} }
@ -3282,7 +3282,7 @@ class Core {
return fetch; return fetch;
} }
private static void reportEmptyMessage(Context context, State state, EntityAccount account, IMAPStore istore) { private static void reportEmptyMessage(Context context, int session, State state, EntityAccount account, IMAPStore istore) {
try { try {
if (istore.hasCapability("ID")) { if (istore.hasCapability("ID")) {
Map<String, String> id = new LinkedHashMap<>(); Map<String, String> id = new LinkedHashMap<>();
@ -3309,7 +3309,7 @@ class Core {
account.partial_fetch = false; account.partial_fetch = false;
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
db.account().setAccountPartialFetch(account.id, account.partial_fetch); db.account().setAccountPartialFetch(account.id, account.partial_fetch);
state.error(new StoreClosedException(istore)); state.error(new StoreClosedException(istore), session);
} }
} }
@ -4052,6 +4052,7 @@ class Core {
} }
static class State { static class State {
private int session;
private int backoff; private int backoff;
private ConnectionHelper.NetworkState networkState; private ConnectionHelper.NetworkState networkState;
private Thread thread = new Thread(); private Thread thread = new Thread();
@ -4101,7 +4102,12 @@ class Core {
return semaphore.tryAcquire(milliseconds, TimeUnit.MILLISECONDS); return semaphore.tryAcquire(milliseconds, TimeUnit.MILLISECONDS);
} }
void error(Throwable ex) { void error(Throwable ex, int session) {
if (session != this.session) {
Log.i("Ignoring session=" + session + "/" + this.session + " ex=" + ex);
return;
}
if (ex instanceof MessagingException && if (ex instanceof MessagingException &&
("connection failure".equals(ex.getMessage()) || ("connection failure".equals(ex.getMessage()) ||
"Not connected".equals(ex.getMessage()) || // POP3 "Not connected".equals(ex.getMessage()) || // POP3
@ -4132,7 +4138,8 @@ class Core {
yield(); yield();
} }
void reset() { void reset(int run) {
session = run;
recoverable = true; recoverable = true;
lastActivity = null; lastActivity = null;
resetBatches(); resetBatches();

View File

@ -904,11 +904,13 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
Log.w(account.name + " backoff " + ex.toString()); Log.w(account.name + " backoff " + ex.toString());
} }
int run = 0;
int errors = 0; int errors = 0;
state.setBackoff(CONNECT_BACKOFF_START); state.setBackoff(CONNECT_BACKOFF_START);
while (state.isRunning() && while (state.isRunning() &&
currentThread != null && currentThread.equals(thread)) { currentThread != null && currentThread.equals(thread)) {
state.reset(); final int session = ++run;
state.reset(session);
Log.i(account.name + " run thread=" + currentThread); Log.i(account.name + " run thread=" + currentThread);
final List<TwoStateOwner> cowners = new ArrayList<>(); final List<TwoStateOwner> cowners = new ArrayList<>();
@ -1131,7 +1133,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
EntityLog.log( EntityLog.log(
ServiceSynchronize.this, ServiceSynchronize.this,
folder.name + " " + Log.formatThrowable(ex, false)); folder.name + " " + Log.formatThrowable(ex, false));
state.error(ex); state.error(ex, session);
} finally { } finally {
wlMessage.release(); wlMessage.release();
} }
@ -1160,7 +1162,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
EntityLog.log( EntityLog.log(
ServiceSynchronize.this, ServiceSynchronize.this,
folder.name + " " + Log.formatThrowable(ex, false)); folder.name + " " + Log.formatThrowable(ex, false));
state.error(ex); state.error(ex, session);
} finally { } finally {
wlMessage.release(); wlMessage.release();
} }
@ -1184,7 +1186,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
EntityLog.log( EntityLog.log(
ServiceSynchronize.this, ServiceSynchronize.this,
folder.name + " " + Log.formatThrowable(ex, false)); folder.name + " " + Log.formatThrowable(ex, false));
state.error(ex); state.error(ex, session);
} finally { } finally {
wlMessage.release(); wlMessage.release();
} }
@ -1207,7 +1209,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
EntityLog.log( EntityLog.log(
ServiceSynchronize.this, ServiceSynchronize.this,
folder.name + " " + Log.formatThrowable(ex, false)); folder.name + " " + Log.formatThrowable(ex, false));
state.error(new FolderClosedException(ifolder, "IDLE")); state.error(new FolderClosedException(ifolder, "IDLE"), session);
} finally { } finally {
Log.i(folder.name + " end idle"); Log.i(folder.name + " end idle");
} }
@ -1343,7 +1345,8 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
Log.i(account.name + " folder " + folder.name + " flags=" + ifolder.getPermanentFlags()); Log.i(account.name + " folder " + folder.name + " flags=" + ifolder.getPermanentFlags());
} }
Core.processOperations(ServiceSynchronize.this, Core.processOperations(
ServiceSynchronize.this, session,
account, folder, account, folder,
partition, partition,
iservice.getStore(), ifolder, iservice.getStore(), ifolder,
@ -1355,7 +1358,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
ServiceSynchronize.this, ServiceSynchronize.this,
folder.name + " " + Log.formatThrowable(ex, false)); folder.name + " " + Log.formatThrowable(ex, false));
db.folder().setFolderError(folder.id, Log.formatThrowable(ex)); db.folder().setFolderError(folder.id, Log.formatThrowable(ex));
state.error(ex); state.error(ex, session);
} finally { } finally {
if (shouldClose) { if (shouldClose) {
if (ifolder != null && ifolder.isOpen()) { if (ifolder != null && ifolder.isOpen()) {