Browse Source

Serialize operations

main
M66B 6 years ago
parent
commit
676eec35c7
2 changed files with 22 additions and 23 deletions
  1. +1
    -2
      app/src/main/java/eu/faircode/email/DaoOperation.java
  2. +21
    -21
      app/src/main/java/eu/faircode/email/ServiceSynchronize.java

+ 1
- 2
app/src/main/java/eu/faircode/email/DaoOperation.java View File

@ -39,8 +39,7 @@ public interface DaoOperation {
@Query("SELECT COUNT(operation.id) FROM operation" + @Query("SELECT COUNT(operation.id) FROM operation" +
" JOIN message ON message.id = operation.message" + " JOIN message ON message.id = operation.message" +
" WHERE folder = :folder" +
" ORDER BY operation.id")
" WHERE folder = :folder")
int getOperationCount(long folder); int getOperationCount(long folder);
@Query("DELETE FROM operation WHERE id = :id") @Query("DELETE FROM operation WHERE id = :id")


+ 21
- 21
app/src/main/java/eu/faircode/email/ServiceSynchronize.java View File

@ -92,7 +92,7 @@ import javax.mail.search.ReceivedDateTerm;
public class ServiceSynchronize extends LifecycleService { public class ServiceSynchronize extends LifecycleService {
private ServiceState state = new ServiceState(); private ServiceState state = new ServiceState();
private ExecutorService executor = Executors.newCachedThreadPool();
private ExecutorService executor = Executors.newSingleThreadExecutor();
private static final int NOTIFICATION_SYNCHRONIZE = 1; private static final int NOTIFICATION_SYNCHRONIZE = 1;
@ -100,8 +100,8 @@ public class ServiceSynchronize extends LifecycleService {
private static final int FETCH_BATCH_SIZE = 10; private static final int FETCH_BATCH_SIZE = 10;
private static final int DOWNLOAD_BUFFER_SIZE = 8192; // bytes private static final int DOWNLOAD_BUFFER_SIZE = 8192; // bytes
static final String ACTION_PROCESS_OUTBOX = BuildConfig.APPLICATION_ID + ".PROCESS_OUTBOX";
static final String ACTION_PROCESS_FOLDER = BuildConfig.APPLICATION_ID + ".PROCESS_FOLDER"; static final String ACTION_PROCESS_FOLDER = BuildConfig.APPLICATION_ID + ".PROCESS_FOLDER";
static final String ACTION_PROCESS_OUTBOX = BuildConfig.APPLICATION_ID + ".PROCESS_OUTBOX";
private class ServiceState { private class ServiceState {
boolean running = false; boolean running = false;
@ -307,13 +307,8 @@ public class ServiceSynchronize extends LifecycleService {
} }
monitorFolder(account, folder, fstore, ifolder); monitorFolder(account, folder, fstore, ifolder);
} catch (FolderNotFoundException ex) { } catch (FolderNotFoundException ex) {
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
// Disable synchronization
folder.synchronize = false;
DB.getInstance(ServiceSynchronize.this).folder().updateFolder(folder);
} catch (Throwable ex) { } catch (Throwable ex) {
Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
reportError(account.name, folder.name, ex); reportError(account.name, folder.name, ex);
@ -341,11 +336,10 @@ public class ServiceSynchronize extends LifecycleService {
} }
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ServiceSynchronize.this); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ServiceSynchronize.this);
lbm.registerReceiver(offline, new IntentFilter(ACTION_PROCESS_FOLDER));
lbm.registerReceiver(processReceiver, new IntentFilter(ACTION_PROCESS_FOLDER));
Log.i(Helper.TAG, "listen process folder"); Log.i(Helper.TAG, "listen process folder");
for (final EntityFolder folder : db.folder().getFolders(account.id, false)) for (final EntityFolder folder : db.folder().getFolders(account.id, false))
if (!EntityFolder.TYPE_OUTBOX.equals(folder.type) &&
db.operation().getOperationCount(folder.id) > 0)
if (!EntityFolder.TYPE_OUTBOX.equals(folder.type))
lbm.sendBroadcast(new Intent(ACTION_PROCESS_FOLDER).putExtra("folder", folder.id)); lbm.sendBroadcast(new Intent(ACTION_PROCESS_FOLDER).putExtra("folder", folder.id));
} catch (Throwable ex) { } catch (Throwable ex) {
@ -366,7 +360,7 @@ public class ServiceSynchronize extends LifecycleService {
Log.e(Helper.TAG, account.name + " disconnected"); Log.e(Helper.TAG, account.name + " disconnected");
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ServiceSynchronize.this); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ServiceSynchronize.this);
lbm.unregisterReceiver(offline);
lbm.unregisterReceiver(processReceiver);
synchronized (mapFolder) { synchronized (mapFolder) {
mapFolder.clear(); mapFolder.clear();
@ -383,7 +377,7 @@ public class ServiceSynchronize extends LifecycleService {
Log.e(Helper.TAG, account.name + " closed"); Log.e(Helper.TAG, account.name + " closed");
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ServiceSynchronize.this); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(ServiceSynchronize.this);
lbm.unregisterReceiver(offline);
lbm.unregisterReceiver(processReceiver);
synchronized (mapFolder) { synchronized (mapFolder) {
mapFolder.clear(); mapFolder.clear();
@ -395,32 +389,40 @@ public class ServiceSynchronize extends LifecycleService {
} }
} }
BroadcastReceiver offline = new BroadcastReceiver() {
BroadcastReceiver processReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
final long fid = intent.getLongExtra("folder", -1); final long fid = intent.getLongExtra("folder", -1);
IMAPFolder x;
IMAPFolder ifolder;
synchronized (mapFolder) { synchronized (mapFolder) {
x = mapFolder.get(fid);
ifolder = mapFolder.get(fid);
} }
final boolean shouldClose = (x == null);
final IMAPFolder ffolder = x;
final boolean shouldClose = (ifolder == null);
final IMAPFolder ffolder = ifolder;
Log.i(Helper.TAG, "run operations folder=" + fid + " offline=" + shouldClose); Log.i(Helper.TAG, "run operations folder=" + fid + " offline=" + shouldClose);
executor.submit(new Runnable() { executor.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
EntityFolder folder = DB.getInstance(ServiceSynchronize.this).folder().getFolder(fid);
DB db = DB.getInstance(ServiceSynchronize.this);
EntityFolder folder = db.folder().getFolder(fid);
IMAPFolder ifolder = ffolder; IMAPFolder ifolder = ffolder;
try { try {
Log.i(Helper.TAG, folder.name + " start operations"); Log.i(Helper.TAG, folder.name + " start operations");
if (ifolder == null) { if (ifolder == null) {
// Prevent unnecessary folder connections
if (db.operation().getOperationCount(fid) == 0)
return;
ifolder = (IMAPFolder) fstore.getFolder(folder.name); ifolder = (IMAPFolder) fstore.getFolder(folder.name);
ifolder.open(Folder.READ_WRITE); ifolder.open(Folder.READ_WRITE);
} }
processOperations(folder, fstore, ifolder); processOperations(folder, fstore, ifolder);
} catch (FolderNotFoundException ex) {
Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
} catch (Throwable ex) { } catch (Throwable ex) {
Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex));
reportError(account.name, folder.name, ex); reportError(account.name, folder.name, ex);
@ -432,7 +434,6 @@ public class ServiceSynchronize extends LifecycleService {
Log.w(Helper.TAG, folder.name + " " + e1 + "\n" + Log.getStackTraceString(e1)); Log.w(Helper.TAG, folder.name + " " + e1 + "\n" + Log.getStackTraceString(e1));
} }
} finally { } finally {
Log.i(Helper.TAG, folder.name + " start operations");
if (shouldClose) if (shouldClose)
if (ifolder != null && ifolder.isOpen()) { if (ifolder != null && ifolder.isOpen()) {
try { try {
@ -577,10 +578,9 @@ public class ServiceSynchronize extends LifecycleService {
} }
}); });
// Listen for process operations requests
// Keep alive
Log.i(Helper.TAG, folder.name + " start"); Log.i(Helper.TAG, folder.name + " start");
try { try {
// Keep alive
Thread thread = new Thread(new Runnable() { Thread thread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {


Loading…
Cancel
Save