scan all files in case some files were previously marked as deleted by accident

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Conversation.java          | 19 
src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java    | 36 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 30 
3 files changed, 72 insertions(+), 13 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -23,6 +23,7 @@ import eu.siacs.conversations.Config;
 import eu.siacs.conversations.crypto.OmemoSetting;
 import eu.siacs.conversations.crypto.PgpDecryptionService;
 import eu.siacs.conversations.crypto.axolotl.AxolotlService;
+import eu.siacs.conversations.persistance.DatabaseBackend;
 import eu.siacs.conversations.services.QuickConversationsService;
 import eu.siacs.conversations.utils.JidHelper;
 import eu.siacs.conversations.xmpp.InvalidJid;
@@ -209,6 +210,24 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 		return deleted;
 	}
 
+	public boolean markAsChanged(final List<DatabaseBackend.FilePathInfo> files) {
+		boolean changed = false;
+		final PgpDecryptionService pgpDecryptionService = account.getPgpDecryptionService();
+		synchronized (this.messages) {
+			for(Message message : this.messages) {
+				for(final DatabaseBackend.FilePathInfo file : files)
+				if (file.uuid.toString().equals(message.getUuid())) {
+					message.setDeleted(file.deleted);
+					changed = true;
+					if (file.deleted && message.getEncryption() == Message.ENCRYPTION_PGP && pgpDecryptionService != null) {
+						pgpDecryptionService.discard(message);
+					}
+				}
+			}
+		}
+		return changed;
+	}
+
 	public void clearMessages() {
 		synchronized (this.messages) {
 			this.messages.clear();

src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java 🔗

@@ -847,12 +847,25 @@ public class DatabaseBackend extends SQLiteOpenHelper {
         db.endTransaction();
     }
 
-    public List<FilePath> getAllNonDeletedFilePath() {
+    public void markFilesAsChanged(List<FilePathInfo> files) {
+        SQLiteDatabase db = this.getReadableDatabase();
+        final String where = Message.UUID + "=?";
+        db.beginTransaction();
+        for (FilePathInfo info : files) {
+            final ContentValues contentValues = new ContentValues();
+            contentValues.put(Message.DELETED, info.deleted ? 1 : 0);
+            db.update(Message.TABLENAME, contentValues, where, new String[]{info.uuid.toString()});
+        }
+        db.setTransactionSuccessful();
+        db.endTransaction();
+    }
+
+    public List<FilePathInfo> getFilePathInfo() {
         final SQLiteDatabase db = this.getReadableDatabase();
-        final Cursor cursor = db.query(Message.TABLENAME, new String[]{Message.UUID, Message.RELATIVE_FILE_PATH}, "type in (1,2) and deleted=0 and "+Message.RELATIVE_FILE_PATH+" is not null", null, null, null, null);
-        final List<FilePath> list = new ArrayList<>();
+        final Cursor cursor = db.query(Message.TABLENAME, new String[]{Message.UUID, Message.RELATIVE_FILE_PATH, Message.DELETED}, "type in (1,2) and "+Message.RELATIVE_FILE_PATH+" is not null", null, null, null, null);
+        final List<FilePathInfo> list = new ArrayList<>();
         while (cursor != null && cursor.moveToNext()) {
-            list.add(new FilePath(cursor.getString(0), cursor.getString(1)));
+            list.add(new FilePathInfo(cursor.getString(0), cursor.getString(1), cursor.getInt(2) > 0));
         }
         if (cursor != null) {
             cursor.close();
@@ -883,6 +896,21 @@ public class DatabaseBackend extends SQLiteOpenHelper {
         }
     }
 
+    public static class FilePathInfo extends FilePath {
+        public boolean deleted;
+
+        private FilePathInfo(String uuid, String path, boolean deleted) {
+            super(uuid,path);
+            this.deleted = deleted;
+        }
+
+        public boolean setDeleted(boolean deleted) {
+            final boolean changed = deleted != this.deleted;
+            this.deleted = deleted;
+            return changed;
+        }
+    }
+
     public Conversation findConversation(final Account account, final Jid contactJid) {
         SQLiteDatabase db = this.getReadableDatabase();
         String[] selectionArgs = {account.getUuid(),

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -1063,22 +1063,24 @@ public class XmppConnectionService extends Service {
             Log.d(Config.LOGTAG, "Do not check for deleted files because service has been destroyed");
             return;
         }
-        final List<String> deletedUuids = new ArrayList<>();
-        final List<DatabaseBackend.FilePath> relativeFilePaths = databaseBackend.getAllNonDeletedFilePath();
-        for(final DatabaseBackend.FilePath filePath : relativeFilePaths) {
+        final long start = SystemClock.elapsedRealtime();
+        final List<DatabaseBackend.FilePathInfo> relativeFilePaths = databaseBackend.getFilePathInfo();
+        final List<DatabaseBackend.FilePathInfo> changed = new ArrayList<>();
+        for(final DatabaseBackend.FilePathInfo filePath : relativeFilePaths) {
             if (destroyed) {
                 Log.d(Config.LOGTAG, "Stop checking for deleted files because service has been destroyed");
                 return;
             }
             final File file = fileBackend.getFileForPath(filePath.path);
-            if (!file.exists()) {
-                deletedUuids.add(filePath.uuid.toString());
+            if (filePath.setDeleted(!file.exists())) {
+                changed.add(filePath);
             }
         }
-        Log.d(Config.LOGTAG,"found "+deletedUuids.size()+" deleted files on start up. total="+relativeFilePaths.size());
-        if (deletedUuids.size() > 0) {
-            databaseBackend.markFileAsDeleted(deletedUuids);
-            markUuidsAsDeletedFiles(deletedUuids);
+        final long duration = SystemClock.elapsedRealtime() - start;
+        Log.d(Config.LOGTAG,"found "+changed.size()+" changed files on start up. total="+relativeFilePaths.size()+". ("+duration+"ms)");
+        if (changed.size() > 0) {
+            databaseBackend.markFilesAsChanged(changed);
+            markChangedFiles(changed);
         }
     }
 
@@ -1671,6 +1673,16 @@ public class XmppConnectionService extends Service {
         }
     }
 
+    private void markChangedFiles(List<DatabaseBackend.FilePathInfo> infos) {
+        boolean changed = false;
+        for (Conversation conversation : getConversations()) {
+            changed |= conversation.markAsChanged(infos);
+        }
+        if (changed) {
+            updateConversationUi();
+        }
+    }
+
 	public void populateWithOrderedConversations(final List<Conversation> list) {
 		populateWithOrderedConversations(list, true, true);
 	}