Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95d75f1b authored by Vincent Bourgmayer's avatar Vincent Bourgmayer
Browse files

Merge branch '687-o-fix-file-ignored' into 'v1-oreo'

implement SQL request to check if there is content to upload in an unchanged directory

See merge request !160
parents 4fecb0e7 05a08adc
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ plugins {

def versionMajor = 1
def versionMinor = 2
def versionPatch = 2
def versionPatch = 3



+35 −0
Original line number Diff line number Diff line
@@ -298,6 +298,41 @@ public final class DbHelper extends SQLiteOpenHelper {
        return result;
    }

    /**
     * Look if there is some known file that need to be uploaded for the given syncedFolder
     * @param syncedFolderID id of the syncedFolder
     * @param context context
     * @return true if there is at least one file that need to be uploaded
     */
    public static boolean syncedFolderHasContentToUpload(long syncedFolderID, Context context) {
        boolean result = false;
        try {
            final SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false);
            result = dao.countFileWaitingForUploadForSyncedFolder(syncedFolderID) > 0;
            dao.close();
        } catch (SQLiteException e) {
            Log.e(TAG, "SQlite error", e);
        }
        return result;
    }

    /**
     * Look if there us some known file that need to be downloaded for the given syncedFolder
     * @param syncedFolderId SyncedFolderId
     * @param context context
     * @return true if there is at least one file to download
     */
    public static boolean syncedFolderHasContentToDownload(int syncedFolderId, Context context) {
        boolean result = false;
        try {
            final SyncedFileStateDAO dao = openSyncedFileStateDAO(context, false);
            result = dao.countFileWaitingForDownloadForSyncedFolder(syncedFolderId) > 0;
            dao.close();
        } catch (SQLiteException e) {
            Log.e(TAG, "SQLite error", e);
        }
        return result;
    }

    /**
     * Copy database file into user accessible directory for debuging purpose
+47 −7
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@ import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteDoneException;
import android.database.sqlite.SQLiteStatement;
import android.util.Log;

import java.util.ArrayList;
@@ -140,12 +142,50 @@ class SyncedFileStateDAO {
        return result;
    }


    /**
     * Count number of SyncedFileState's entry with an empty eTAG for the given syncedFolder.
     * ONLY list file that can be scan on device side
     * @param syncedFolderId ID of the given synced folder
     * @return number of file waiting to be uploaded
     * @throws SQLiteDoneException SQL return 0 rows
     */
    long countFileWaitingForUploadForSyncedFolder(long syncedFolderId) throws SQLiteDoneException {
        final String query = "SELECT COUNT(*) FROM "
            + TABLE_NAME
            + " WHERE " + SCANNABLE + " >= 2"
            + " AND " + LAST_ETAG + " = \"\""
            + " AND " + SYNCEDFOLDER_ID + " = "+syncedFolderId;

        final SQLiteStatement statement = mDB.compileStatement(query);
        return statement.simpleQueryForLong();
    }

    /**
     * Count number of syncedFileState's entry with an eTag but no value for local last modified
     * Only file that can be scan on cloud are listed
     * @param syncedFolderId The id of the syncedFolder
     * @return number of file waiting to be downloaded
     * @throws SQLiteDoneException SQL return 0 rows
     */
    long countFileWaitingForDownloadForSyncedFolder(int syncedFolderId) throws SQLiteDoneException{
        final String query = "SELECT COUNT(*) FROM "
                + TABLE_NAME
                + " WHERE " + SCANNABLE + " IN (1,3)"
                + " AND " + LOCAL_LAST_MODIFIED + " = 0"
                + " AND length(" + LAST_ETAG + ") > 0"
                + " AND " + SYNCEDFOLDER_ID + " = "+syncedFolderId;

        final SQLiteStatement statement = mDB.compileStatement(query);
        return statement.simpleQueryForLong();
    }

    /**
    * Fetch many SyncedFileState by its localPath
    * @param syncedFolderids List<String> of path to filter. Need to be directory path
    * Fetch many SyncedFileState by their syncedFolder's id
    * @param syncedFolderIds List<Long> of id of parent syncedFolder.
    * @return List<SyncedFileState> List of SyncedFileState filtered on syncedFolder ID.
    */
    List<SyncedFileState> getBySyncedFolderID(List<Long> syncedFolderids) {
    List<SyncedFileState> getBySyncedFolderID(List<Long> syncedFolderIds) {
         String query = "Select "
            +SyncedFileStateContract._ID+", "
            +FILE_NAME+", "
@@ -158,11 +198,11 @@ class SyncedFileStateDAO {
            + SCANNABLE
            +" FROM "
            +TABLE_NAME;
         if (syncedFolderids.size() > 0) {
         if (syncedFolderIds.size() > 0) {
             query+=" WHERE ";

             for (int i = -1, idsSize = syncedFolderids.size(); ++i < idsSize; ) {
                 query += SYNCEDFOLDER_ID + " = " + syncedFolderids.get(i);
             for (int i = -1, idsSize = syncedFolderIds.size(); ++i < idsSize; ) {
                 query += SYNCEDFOLDER_ID + " = " + syncedFolderIds.get(i);
                 if (i < idsSize - 1) {
                     query += " OR ";
                 }
+2 −1
Original line number Diff line number Diff line
@@ -113,7 +113,8 @@ public class ListFileRemoteOperation extends RemoteOperation<ArrayList<RemoteFil
        final int dataSize = result.getData().size();
        final RemoteFile directory = (RemoteFile) result.getData().get(0);

        if (directory.getEtag().equals(syncedFolder.getLastEtag())) {
        if (directory.getEtag().equals(syncedFolder.getLastEtag())
        && !DbHelper.syncedFolderHasContentToDownload(syncedFolder.getId(), context)) {
            return false;
        }
        syncedFolder.setLastEtag(directory.getEtag()).setToSync(true);
+33 −63
Original line number Diff line number Diff line
@@ -404,100 +404,70 @@ public class ObserverService extends Service implements OnRemoteOperationListene
     */
    private void scanLocalFiles(){
        Log.i( TAG, "scanLocalFiles()" );
        List<File> fileList = new ArrayList<>();
        List<Long> folderIdList= new ArrayList<>();
        final List<File> fileList = new ArrayList<>();
        final List<Long> folderIdList= new ArrayList<>();
        boolean contentToSyncFound = false;
        //Regenere list of application's package
        if (CommonUtils.isSettingsSyncEnabled(mAccount)) generateAppListFile();


        if (CommonUtils.isSettingsSyncEnabled(mAccount)) generateAppListFile();
        final ListIterator<SyncedFolder> iterator = mSyncedFolders.listIterator() ;
        //Loop through folders

        while(iterator.hasNext()) {
            final SyncedFolder syncedFolder = iterator.next();
            Log.d(TAG, "SyncedFolder :"+syncedFolder.getLibelle()+", "+syncedFolder.getLocalFolder()+", "+syncedFolder.getLastModified()+", "+syncedFolder.isScanLocal()+", "+syncedFolder.getId() );

            //Check it's not a hidden file
            String fileName = CommonUtils.getFileNameFromPath(syncedFolder.getLocalFolder());
            if (fileName == null) {
                Log.e(TAG, "getFileNameFromPath() returned null. Returning to prevent a NPE");
                return;
            }

            if (syncedFolder.isMediaType() && fileName.startsWith(".")){
                iterator.remove();
                continue;
            }

            //Check it can be scann from local
            if (!syncedFolder.isScanLocal()){
            final String fileName = CommonUtils.getFileNameFromPath(syncedFolder.getLocalFolder());
            if (fileName == null || fileName.startsWith(".") || !syncedFolder.isScanLocal()) {
                iterator.remove();
                continue;
            }

            //Check if it's a new folder
            if (syncedFolder.getId() == -1) {
                Log.v(TAG, "This is a new folder, we must register it");
                //persist new syncedFolder
                int syncedFolder_id = (int) DbHelper.insertSyncedFolder(syncedFolder, this); //It will return -1 if there is an error, like an already existing folder with same value
                if (syncedFolder_id > 0) {
                    Log.v(TAG, "Folder has been registered in DB");
                    syncedFolder.setId(syncedFolder_id);
                } else {
                    Log.w(TAG, "syncedFolder " + syncedFolder.getLocalFolder() + " remove iterator because it hasn't been registered in DB or already stored");
                final int syncedFolder_id = (int) DbHelper.insertSyncedFolder(syncedFolder, this); //It will return -1 if there is an error, like an already existing folder with same value
                if (syncedFolder_id <= 0) {
                    iterator.remove();
                    continue;
                }
                syncedFolder.setId(syncedFolder_id);
            }
            //Get local folder corresponding
            File localFolder = new File(syncedFolder.getLocalFolder()); //Obtention du fichier local
            Log.d(TAG, "Local Folder (last modified / exists): "+localFolder.lastModified()+", "+localFolder.exists() );

            //Check if local folder exists
            if (!localFolder.exists()){
                Log.v(TAG, "local folder doesn't exist anymore . So content has change");

            final File localDirectory = new File(syncedFolder.getLocalFolder()); //Obtention du fichier local
            Log.d(TAG, "Local Folder (last modified / exists): "+localDirectory.lastModified()+", "+localDirectory.exists() );

            if (!localDirectory.exists()) {
                contentToSyncFound = true;
                folderIdList.add( (long) syncedFolder.getId() );
                continue;
            }

            boolean folderHasChange = false; //consider by default that file hadn't change

            //Check if folder had change
            if (localFolder.lastModified() > syncedFolder.getLastModified() ) { //compare last modified date
                Log.v(TAG, "local folder has changed");
                syncedFolder.setLastModified( localFolder.lastModified() ); //@Todo: it would be better to set it after all it's content has been synced
                contentToSyncFound = true; //at least one dir has changed
                folderHasChange = true; //The folder has change
                folderIdList.add( (long) syncedFolder.getId() ); //add id into list of modified folder
            if (localDirectory.lastModified() > syncedFolder.getLastModified()
                || DbHelper.syncedFolderHasContentToUpload(syncedFolder.getId(), getApplicationContext())) {
                syncedFolder.setLastModified(localDirectory.lastModified()); //@Todo: it would be better to set it after all it's content has been synced
                contentToSyncFound = true;
                folderIdList.add((long) syncedFolder.getId());
            }

            //Get sub files

            final FileFilter filter = FileFilterFactory.getFileFilter( (syncedFolder.isMediaType()) ? "media" : syncedFolder.getLibelle() );
            File[] subElements = localFolder.listFiles(filter); //hiden media files are being ignored

            Log.v(TAG, "loop through subfiles");
            for (int i = -1, subEltSize = (subElements != null)? subElements.length: 0; ++i < subEltSize; ) {
                File subElt = subElements[i];
                if (subElt == null) continue;
                if (subElt.isDirectory()) { //if its a subfolder add it to syncedFolder list
                    //if a subfolder is found, add it to syncedFolder list
                    Log.v(TAG, "subfile "+subElt.getAbsolutePath()+" is a directory.");
                    SyncedFolder subSyncedFolder = new SyncedFolder(syncedFolder, subElt.getName() + FileUtils.PATH_SEPARATOR, 0L, "");//Need to put 0 into to be handled on next iterati
            final File[] subFiles = localDirectory.listFiles(filter); //skip hidden media files

            if (subFiles == null) continue;
            for (File subFile : subFiles) {
                if (subFile.isDirectory()) {
                    final SyncedFolder subSyncedFolder = new SyncedFolder(syncedFolder, subFile.getName() + FileUtils.PATH_SEPARATOR, 0L, "");//Need to set lastModified to 0 to handle it on next iteration
                    iterator.add(subSyncedFolder);
                    iterator.previous();

                } else {
                    if (folderHasChange) { //only consider files if folder had change
                        Log.v(TAG, "subfile " + subElt.getAbsolutePath() + " is a file added to list of file to sync");
                        fileList.add(subElt);
                } else if (contentToSyncFound) {
                    Log.v(TAG, "added subfile " + subFile.getAbsolutePath() + " into list of file to sync");
                    fileList.add(subFile);
                }
            }
        }
        } //end of iterator loop

        if (contentToSyncFound) {
            DbHelper.updateSyncedFolders(mSyncedFolders, this); //@ToDo: maybe do this when all contents will be synced.
            List<SyncedFileState> syncedFileStates = DbHelper.getSyncedFileStatesByFolders(this,
            final List<SyncedFileState> syncedFileStates = DbHelper.getSyncedFileStatesByFolders(this,
                    folderIdList);

            if (!syncedFileStates.isEmpty() || !fileList.isEmpty() ) {
Loading