Loading app/src/main/java/foundation/e/drive/services/ObserverService.java +13 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading app/src/main/java/foundation/e/drive/utils/FileDiffUtils.java 0 → 100644 +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(); } } Loading
app/src/main/java/foundation/e/drive/services/ObserverService.java +13 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading
app/src/main/java/foundation/e/drive/utils/FileDiffUtils.java 0 → 100644 +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(); } }