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

Commit fd55d73f authored by Vincent Bourgmayer's avatar Vincent Bourgmayer
Browse files

Extract code about fileDiff beetween RemoteFile & Database or local file

 into a dedicated class.

Clean ObserverService.handleRemoteFile part about fileDiff checking
parent 65aa4d30
Loading
Loading
Loading
Loading
Loading
+13 −22
Original line number Diff line number Diff line
@@ -47,11 +47,13 @@ import foundation.e.drive.receivers.DebugCmdReceiver;
import foundation.e.drive.utils.AppConstants;
import foundation.e.drive.utils.CommonUtils;
import foundation.e.drive.utils.DavClientProvider;
import foundation.e.drive.utils.FileDiffUtils;
import foundation.e.drive.utils.ServiceExceptionHandler;
import foundation.e.drive.utils.SynchronizationServiceConnection;

import static com.owncloud.android.lib.resources.files.FileUtils.PATH_SEPARATOR;
import static foundation.e.drive.utils.AppConstants.INITIALIZATION_HAS_BEEN_DONE;
import static foundation.e.drive.utils.FileDiffUtils.getActionForFileDiff;

import androidx.annotation.Nullable;

@@ -380,41 +382,30 @@ public class ObserverService extends Service implements OnRemoteOperationListene
                    continue;
                }

                Log.v(TAG, "syncedFileState.getRemotePath() :"+syncedFileState.getRemotePath() );

                //If syncedFileState match the remote file
                if (remoteFilePath.equals(syncedFileState.getRemotePath())) {
                    Log.d(TAG, "correspondant found for "+remoteFilePath );
                    correspondant_found = true;

                    if (syncedFileState.isLastEtagStored() //there is an etag stored
                        && (!remoteFile.getEtag().equals(syncedFileState.getLastETAG()) //If etag has changed
                        || syncedFileState.getLocalLastModified() == 0L)) { //File hasn't been downloaded
                    final FileDiffUtils.Action action = getActionForFileDiff(remoteFile, syncedFileState);
                    if (action == FileDiffUtils.Action.Download) {

                        Log.v(TAG, "etag and localLastModified are valids for "+remoteFilePath );
                        Log.i(TAG, "Add download operation for file "+syncedFileState.getId());
                        this.syncRequests.put(syncedFileState.getId(), new DownloadRequest(remoteFile, syncedFileState));

                        //compare size with local file
                        if (remoteFile.getLength() == new File(syncedFileState.getLocalPath()).length()) { //length is 0 is file doesn't exist
                            Log.v(TAG, "file size are the same for local and remote, just update syncedFileState etag");
                    } else if (action == FileDiffUtils.Action.updateDB) {

                        syncedFileState.setLastETAG(remoteFile.getEtag());
                            int affectedRows = DbHelper.manageSyncedFileStateDB(syncedFileState, "UPDATE", this);
                            Log.v(TAG, affectedRows + " syncedFileState.s row in DB has been updated.");
                        } else {
                            Log.i(TAG, "Add download operation for file "+syncedFileState.getId());

                            this.syncRequests.put(syncedFileState.getId(), new DownloadRequest(remoteFile, syncedFileState));
                        final int affectedRows = DbHelper.manageSyncedFileStateDB(syncedFileState, "UPDATE", this);
                        if (affectedRows == 0) Log.e(TAG, "Error while updating eTag in DB for: "+remoteFilePath);
                    }
                    }
                    syncedFileListIterator.remove(); //we can delete syncedFile from list because its correspondant has already been found and handled
                    syncedFileListIterator.remove();
                    break;
                }
            }

            if (correspondant_found) continue;

            //If we get here, RemoteFile is a new file to download
            Log.v(TAG, "SyncedFileState corresponding to remoteFile not found.");
            Log.v(TAG, remoteFilePath + "is a new file");

            //Extract parent folder's path of remote file
            final String parentOfKnownPath = remoteFilePath.substring(0, remoteFilePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1);
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright © ECORP SAS 2022.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 */
package foundation.e.drive.utils;

import com.owncloud.android.lib.resources.files.model.RemoteFile;

import java.io.File;

import foundation.e.drive.models.SyncedFileState;

/**
 * This class encapsulate code to compare syncedFile & Remote file
 * but also RemoteFolder and SyncedFolder
 * @author vincent Bourgmayer
 */
public class FileDiffUtils {

    public enum Action {
        Upload,
        Download,
        Remove,
        skip,
        updateDB
    }


    /**
     * Define what to do of RemoteFile for which we know the Database equivalent
     * @param remoteFile RemoteFile
     * @param fileState SyncedFileState instance
     * @return Action from Enum
     */
    public static Action getActionForFileDiff(RemoteFile remoteFile, SyncedFileState fileState) {
        if (hasAlreadyBeenDownloaded(fileState) && !hasEtagChanged(remoteFile, fileState)) {
            return Action.skip;
        }
        final File localFile = new File(fileState.getLocalPath());
        if (isRemoteSizeSameAsLocalSize(remoteFile, localFile)) {
            return Action.updateDB;
        } else {
            return Action.Download;
        }
    }

    /**
     * Compare RemoteFile's eTag with the one stored in Database
     * @param file RemoteFile
     * @param fileState last store file's state
     * @return true if ETag
     */
    private static boolean hasEtagChanged(RemoteFile file, SyncedFileState fileState) {
        //if SyncedFileState has no Etag then it hasn't been uploaded and so must not exist on server
        return fileState.isLastEtagStored() && !file.getEtag().equals(fileState.getLastETAG());
    }

    /**
     * Indicate if the file has already been downloaded
     * or detected on the device
     * @param fileState SyncedFileState containing data from Database
     * @return true if localLastModified store in Database == 0
     */
    private static boolean hasAlreadyBeenDownloaded(SyncedFileState fileState) {
        return fileState.getLocalLastModified() == 0l;
    }

    /**
     *
     * @param remoteFile RemoteFile instance
     * @param localFile File instance
     * @return true if remote file size is same as local file size
     */
    private static boolean isRemoteSizeSameAsLocalSize(RemoteFile remoteFile, File localFile) {
        // if local file doesn't exist its size will be 0
        return remoteFile.getLength() == localFile.length();
    }
}