mirror of https://github.com/M66B/FairEmail.git
Fixed hanging wait operations
This commit is contained in:
parent
e6d933c231
commit
24a479806e
File diff suppressed because it is too large
Load Diff
|
@ -481,8 +481,10 @@ class Core {
|
|||
|
||||
boolean autoread = (jargs.length() > 1 && jargs.getBoolean(1));
|
||||
|
||||
boolean canMove = istore.hasCapability("MOVE");
|
||||
if (!copy && canMove &&
|
||||
long uid;
|
||||
if (!copy &&
|
||||
istore.hasCapability("MOVE") &&
|
||||
istore.hasCapability("UIDPLUS") &&
|
||||
!EntityFolder.DRAFTS.equals(folder.type) &&
|
||||
!EntityFolder.DRAFTS.equals(target.type)) {
|
||||
// Autoread
|
||||
|
@ -490,12 +492,14 @@ class Core {
|
|||
if (autoread && !imessage.isSet(Flags.Flag.SEEN))
|
||||
imessage.setFlag(Flags.Flag.SEEN, true);
|
||||
|
||||
// Move message to
|
||||
ifolder.moveMessages(new Message[]{imessage}, itarget);
|
||||
// Move message to target folder
|
||||
AppendUID[] uids = ifolder.moveUIDMessages(new Message[]{imessage}, itarget);
|
||||
if (uids == null || uids.length == 0)
|
||||
throw new MessageRemovedException("Message not moved");
|
||||
uid = uids[0].uid;
|
||||
} else {
|
||||
if (!copy)
|
||||
Log.w(folder.name + " MOVE by DELETE/APPEND" +
|
||||
" cap=" + canMove + " from=" + folder.type + " to=" + target.type);
|
||||
Log.w(folder.name + " MOVE by DELETE/APPEND");
|
||||
|
||||
// Serialize source message
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
@ -532,42 +536,63 @@ class Core {
|
|||
icopy.setFlag(Flags.Flag.DRAFT, true);
|
||||
|
||||
// Append target
|
||||
long uid = append(istore, itarget, (MimeMessage) icopy);
|
||||
Log.i(target.name + " appended id=" + message.id + " uid=" + uid);
|
||||
uid = append(istore, itarget, (MimeMessage) icopy);
|
||||
|
||||
// Fixed timing issue of at least Courier based servers
|
||||
itarget.close(false);
|
||||
itarget.open(Folder.READ_WRITE);
|
||||
try {
|
||||
// Fixed timing issue of at least Courier based servers
|
||||
itarget.close(false);
|
||||
itarget.open(Folder.READ_WRITE);
|
||||
|
||||
// Some providers, like Gmail, don't honor the appended seen flag
|
||||
if (itarget.getPermanentFlags().contains(Flags.Flag.SEEN)) {
|
||||
boolean seen = (autoread || message.ui_seen);
|
||||
icopy = itarget.getMessageByUID(uid);
|
||||
if (seen != icopy.isSet(Flags.Flag.SEEN)) {
|
||||
Log.i(target.name + " Fixing id=" + message.id + " seen=" + seen);
|
||||
icopy.setFlag(Flags.Flag.SEEN, seen);
|
||||
// Some providers, like Gmail, don't honor the appended seen flag
|
||||
if (itarget.getPermanentFlags().contains(Flags.Flag.SEEN)) {
|
||||
boolean seen = (autoread || message.ui_seen);
|
||||
icopy = itarget.getMessageByUID(uid);
|
||||
if (seen != icopy.isSet(Flags.Flag.SEEN)) {
|
||||
Log.i(target.name + " Fixing id=" + message.id + " seen=" + seen);
|
||||
icopy.setFlag(Flags.Flag.SEEN, seen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is not based on an actual case, so this is just a safeguard
|
||||
if (itarget.getPermanentFlags().contains(Flags.Flag.DRAFT)) {
|
||||
boolean draft = EntityFolder.DRAFTS.equals(target.type);
|
||||
icopy = itarget.getMessageByUID(uid);
|
||||
if (draft != icopy.isSet(Flags.Flag.DRAFT)) {
|
||||
Log.i(target.name + " Fixing id=" + message.id + " draft=" + draft);
|
||||
icopy.setFlag(Flags.Flag.DRAFT, draft);
|
||||
// This is not based on an actual case, so this is just a safeguard
|
||||
if (itarget.getPermanentFlags().contains(Flags.Flag.DRAFT)) {
|
||||
boolean draft = EntityFolder.DRAFTS.equals(target.type);
|
||||
icopy = itarget.getMessageByUID(uid);
|
||||
if (draft != icopy.isSet(Flags.Flag.DRAFT)) {
|
||||
Log.i(target.name + " Fixing id=" + message.id + " draft=" + draft);
|
||||
icopy.setFlag(Flags.Flag.DRAFT, draft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete source
|
||||
if (!copy) {
|
||||
imessage.setFlag(Flags.Flag.DELETED, true);
|
||||
ifolder.expunge();
|
||||
// Delete source
|
||||
if (!copy) {
|
||||
imessage.setFlag(Flags.Flag.DELETED, true);
|
||||
ifolder.expunge();
|
||||
}
|
||||
} catch (MessageRemovedException ignored) {
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
} finally {
|
||||
if (itarget.isOpen())
|
||||
itarget.close();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(folder.name + " moved uid=" + uid);
|
||||
if (jargs.length() > 2) {
|
||||
long tmpid = jargs.getLong(2);
|
||||
try {
|
||||
db.beginTransaction();
|
||||
db.message().setMessageUid(tmpid, uid);
|
||||
int waits = -1;
|
||||
if (jargs.length() > 3) {
|
||||
long waitid = jargs.getLong(3);
|
||||
waits = db.operation().deleteOperation(waitid);
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
Log.i(folder.name + " set id=" + tmpid + " uid=" + uid + " waits=" + waits);
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1293,10 +1318,6 @@ class Core {
|
|||
db.message().updateMessage(message);
|
||||
else if (BuildConfig.DEBUG)
|
||||
Log.i(folder.name + " unchanged uid=" + uid);
|
||||
|
||||
int wait = db.operation().deleteOperationWait(message.id);
|
||||
if (wait > 0)
|
||||
Log.i(folder.name + " deleted wait id=" + message.id);
|
||||
}
|
||||
|
||||
if (!folder.isOutgoing() && !EntityFolder.ARCHIVE.equals(folder.type)) {
|
||||
|
|
|
@ -49,7 +49,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
|
|||
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||
|
||||
@Database(
|
||||
version = 50,
|
||||
version = 51,
|
||||
entities = {
|
||||
EntityIdentity.class,
|
||||
EntityAccount.class,
|
||||
|
@ -546,6 +546,13 @@ public abstract class DB extends RoomDatabase {
|
|||
db.execSQL("CREATE INDEX `index_message_subject` ON `message` (`subject`)");
|
||||
}
|
||||
})
|
||||
.addMigrations(new Migration(50, 51) {
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase db) {
|
||||
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
||||
db.execSQL("DELETE FROM operation WHERE name = '" + EntityOperation.WAIT + "'");
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -94,11 +94,6 @@ public interface DaoOperation {
|
|||
@Insert
|
||||
long insertOperation(EntityOperation operation);
|
||||
|
||||
@Query("DELETE FROM operation" +
|
||||
" WHERE message = :message" +
|
||||
" AND name = '" + EntityOperation.WAIT + "'")
|
||||
int deleteOperationWait(long message);
|
||||
|
||||
@Query("DELETE FROM operation WHERE id = :id")
|
||||
void deleteOperation(long id);
|
||||
int deleteOperation(long id);
|
||||
}
|
||||
|
|
|
@ -108,6 +108,8 @@ public class EntityOperation {
|
|||
// Parameters:
|
||||
// 0: target folder id
|
||||
// 1: allow auto read
|
||||
// 2: temporary target message id
|
||||
// 3: wait operation id
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean autoread = prefs.getBoolean("autoread", false);
|
||||
|
@ -132,11 +134,12 @@ public class EntityOperation {
|
|||
|
||||
// Create copy without uid in target folder
|
||||
// Message with same msgid can be in archive
|
||||
Long newid = null;
|
||||
Long tmpid = null;
|
||||
if (message.uid != null &&
|
||||
target.synchronize &&
|
||||
message.received > cal_keep.getTimeInMillis() &&
|
||||
db.message().countMessageByMsgId(target.id, message.msgid) == 0) {
|
||||
// Copy message to target folder
|
||||
long id = message.id;
|
||||
long uid = message.uid;
|
||||
boolean seen = message.seen;
|
||||
|
@ -149,9 +152,8 @@ public class EntityOperation {
|
|||
message.seen = true;
|
||||
message.ui_seen = true;
|
||||
}
|
||||
newid = db.message().insertMessage(message);
|
||||
message.id = newid;
|
||||
queue(context, db, message, WAIT);
|
||||
tmpid = db.message().insertMessage(message);
|
||||
|
||||
message.id = id;
|
||||
message.account = source.account;
|
||||
message.folder = source.id;
|
||||
|
@ -163,33 +165,48 @@ public class EntityOperation {
|
|||
try {
|
||||
Helper.copy(
|
||||
EntityMessage.getFile(context, id),
|
||||
EntityMessage.getFile(context, newid));
|
||||
EntityMessage.getFile(context, tmpid));
|
||||
} catch (IOException ex) {
|
||||
Log.e(ex);
|
||||
db.message().setMessageContent(newid, false, null, null);
|
||||
db.message().setMessageContent(tmpid, false, null, null);
|
||||
}
|
||||
|
||||
EntityAttachment.copy(context, db, message.id, newid);
|
||||
|
||||
// Store new id for when source message was deleted
|
||||
jargs.put(2, newid);
|
||||
EntityAttachment.copy(context, db, message.id, tmpid);
|
||||
}
|
||||
|
||||
// Cross account move
|
||||
if (!source.account.equals(target.account))
|
||||
if (source.account.equals(target.account)) {
|
||||
jargs.put(2, tmpid);
|
||||
|
||||
// Block operations until message is moved
|
||||
JSONArray wargs = new JSONArray();
|
||||
wargs.put(source.id);
|
||||
wargs.put(message.id);
|
||||
|
||||
EntityOperation wait = new EntityOperation();
|
||||
wait.folder = target.id;
|
||||
wait.message = tmpid;
|
||||
wait.name = EntityOperation.WAIT;
|
||||
wait.args = wargs.toString();
|
||||
wait.created = new Date().getTime();
|
||||
wait.id = db.operation().insertOperation(wait);
|
||||
|
||||
jargs.put(3, wait.id);
|
||||
} else {
|
||||
if (message.raw != null && message.raw) {
|
||||
name = ADD;
|
||||
folder = target.id;
|
||||
jargs = new JSONArray();
|
||||
jargs.put(0, newid); // Can be null
|
||||
jargs.put(0, tmpid); // Can be null
|
||||
jargs.put(1, autoread);
|
||||
} else {
|
||||
name = RAW;
|
||||
jargs = new JSONArray();
|
||||
jargs.put(0, newid); // Can be null
|
||||
jargs.put(0, tmpid); // Can be null
|
||||
jargs.put(1, autoread);
|
||||
jargs.put(2, target.id);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (DELETE.equals(name))
|
||||
db.message().setMessageUiHide(message.id, true);
|
||||
|
|
Loading…
Reference in New Issue