X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/9093ef8f9fc64c290d0fed5f66106fa6a20330df..afaa2879d192be067cae523b51dad75d89a6c6cb:/src/com/owncloud/android/services/SyncFolderHandler.java diff --git a/src/com/owncloud/android/services/SyncFolderHandler.java b/src/com/owncloud/android/services/SyncFolderHandler.java index 171a2f2d..33318f57 100644 --- a/src/com/owncloud/android/services/SyncFolderHandler.java +++ b/src/com/owncloud/android/services/SyncFolderHandler.java @@ -1,4 +1,6 @@ -/* ownCloud Android client application +/** + * ownCloud Android client application + * * Copyright (C) 2015 ownCloud Inc. * * This program is free software: you can redistribute it and/or modify @@ -25,9 +27,11 @@ import android.os.Looper; import android.os.Message; import android.util.Pair; +import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; +import com.owncloud.android.files.services.IndexedForest; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; @@ -37,10 +41,6 @@ import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.utils.FileStorageUtils; import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; /** * SyncFolder worker. Performs the pending operations in the order they were requested. @@ -55,9 +55,11 @@ class SyncFolderHandler extends Handler { OperationsService mService; - private ConcurrentMap mPendingOperations = - new ConcurrentHashMap(); + private IndexedForest mPendingOperations = + new IndexedForest(); + private OwnCloudClient mOwnCloudClient = null; + private Account mCurrentAccount = null; private FileDataStorageManager mStorageManager; private SynchronizeFolderOperation mCurrentSyncOperation; @@ -71,18 +73,16 @@ class SyncFolderHandler extends Handler { } + /** + * Returns True when the folder located in 'remotePath' in the ownCloud account 'account', or any of its + * descendants, is being synchronized (or waiting for it). + * + * @param account ownCloud account where the remote folder is stored. + * @param remotePath The path to a folder that could be in the queue of synchronizations. + */ public boolean isSynchronizing(Account account, String remotePath) { if (account == null || remotePath == null) return false; - String targetKey = buildRemoteName(account, remotePath); - synchronized (mPendingOperations) { - // TODO - this can be slow when synchronizing a big tree - need a better data structure - Iterator it = mPendingOperations.keySet().iterator(); - boolean found = false; - while (it.hasNext() && !found) { - found = it.next().startsWith(targetKey); - } - return found; - } + return (mPendingOperations.contains(account, remotePath)); } @@ -90,6 +90,7 @@ class SyncFolderHandler extends Handler { public void handleMessage(Message msg) { Pair itemSyncKey = (Pair) msg.obj; doOperation(itemSyncKey.first, itemSyncKey.second); + Log_OC.d(TAG, "Stopping after command with id " + msg.arg1); mService.stopSelf(msg.arg1); } @@ -99,95 +100,71 @@ class SyncFolderHandler extends Handler { */ private void doOperation(Account account, String remotePath) { - String syncKey = buildRemoteName(account,remotePath); - - synchronized(mPendingOperations) { - mCurrentSyncOperation = mPendingOperations.get(syncKey); - } + mCurrentSyncOperation = mPendingOperations.get(account, remotePath); if (mCurrentSyncOperation != null) { RemoteOperationResult result = null; try { + if (mCurrentAccount == null || !mCurrentAccount.equals(account)) { + mCurrentAccount = account; + mStorageManager = new FileDataStorageManager( + account, + mService.getContentResolver() + ); + } // else, reuse storage manager from previous operation + + // always get client from client manager, to get fresh credentials in case of update OwnCloudAccount ocAccount = new OwnCloudAccount(account, mService); mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). getClientFor(ocAccount, mService); - mStorageManager = new FileDataStorageManager( - account, - mService.getContentResolver() - ); result = mCurrentSyncOperation.execute(mOwnCloudClient, mStorageManager); } catch (AccountsException e) { - Log_OC.e(TAG, "Error while trying to get autorization", e); + Log_OC.e(TAG, "Error while trying to get authorization", e); } catch (IOException e) { - Log_OC.e(TAG, "Error while trying to get autorization", e); + Log_OC.e(TAG, "Error while trying to get authorization", e); } finally { - synchronized (mPendingOperations) { - mPendingOperations.remove(syncKey); - /* - SynchronizeFolderOperation checkedOp = mCurrentSyncOperation; - String checkedKey = syncKey; - while (checkedOp.getPendingChildrenCount() <= 0) { - // while (!checkedOp.hasChildren()) { - mPendingOperations.remove(checkedKey); - String parentKey = buildRemoteName(account, (new File(checkedOp.getFolderPath())).getParent()); - // String parentKey = buildRemoteName(account, checkedOp.getParentPath()); - SynchronizeFolderOperation parentOp = mPendingOperations.get(parentKey); - if (parentOp != null) { - parentOp.decreasePendingChildrenCount(); - } - } - */ - } - - mService.dispatchResultToOperationListeners(null, mCurrentSyncOperation, result); + mPendingOperations.removePayload(account, remotePath); + + mService.dispatchResultToOperationListeners(mCurrentSyncOperation, result); sendBroadcastFinishedSyncFolder(account, remotePath, result.isSuccess()); } } } - public void add(Account account, String remotePath, SynchronizeFolderOperation syncFolderOperation){ - String syncKey = buildRemoteName(account,remotePath); - mPendingOperations.putIfAbsent(syncKey,syncFolderOperation); - sendBroadcastNewSyncFolder(account, remotePath); + public void add(Account account, String remotePath, + SynchronizeFolderOperation syncFolderOperation){ + mPendingOperations.putIfAbsent(account, remotePath, syncFolderOperation); + sendBroadcastNewSyncFolder(account, remotePath); // TODO upgrade! } + /** - * Cancels sync operations. - * @param account Owncloud account where the remote file is stored. - * @param file File OCFile + * Cancels a pending or current sync' operation. + * + * @param account ownCloud account where the remote file is stored. + * @param file A file in the queue of pending synchronizations */ public void cancel(Account account, OCFile file){ - SynchronizeFolderOperation syncOperation = null; - String targetKey = buildRemoteName(account, file.getRemotePath()); - ArrayList keyItems = new ArrayList(); - synchronized (mPendingOperations) { - if (file.isFolder()) { - Log_OC.d(TAG, "Canceling pending sync operations"); - Iterator it = mPendingOperations.keySet().iterator(); - boolean found = false; - while (it.hasNext()) { - String keySyncOperation = it.next(); - found = keySyncOperation.startsWith(targetKey); - if (found) { - keyItems.add(keySyncOperation); - } - } - - } else { - // this is not really expected... - Log_OC.d(TAG, "Canceling sync operation"); - keyItems.add(buildRemoteName(account, file.getRemotePath())); - } - for (String item: keyItems) { - syncOperation = mPendingOperations.remove(item); - if (syncOperation != null) { - syncOperation.cancel(); - } + if (account == null || file == null) { + Log_OC.e(TAG, "Cannot cancel with NULL parameters"); + return; + } + Pair removeResult = + mPendingOperations.remove(account, file.getRemotePath()); + SynchronizeFolderOperation synchronization = removeResult.first; + if (synchronization != null) { + synchronization.cancel(); + } else { + // TODO synchronize? + if (mCurrentSyncOperation != null && mCurrentAccount != null && + mCurrentSyncOperation.getRemotePath().startsWith(file.getRemotePath()) && + account.name.equals(mCurrentAccount.name)) { + mCurrentSyncOperation.cancel(); } } @@ -195,37 +172,29 @@ class SyncFolderHandler extends Handler { } /** - * Builds a key from the account and file to download - * - * @param account Account where the file to download is stored - * @param path File path - */ - private String buildRemoteName(Account account, String path) { - return account.name + path; - } - - - /** - * TODO review this method when "folder synchronization" replaces "folder download"; this is a fast and ugly - * patch. + * TODO review this method when "folder synchronization" replaces "folder download"; + * this is a fast and ugly patch. */ private void sendBroadcastNewSyncFolder(Account account, String remotePath) { Intent added = new Intent(FileDownloader.getDownloadAddedMessage()); added.putExtra(FileDownloader.ACCOUNT_NAME, account.name); added.putExtra(FileDownloader.EXTRA_REMOTE_PATH, remotePath); - added.putExtra(FileDownloader.EXTRA_FILE_PATH, FileStorageUtils.getSavePath(account.name) + remotePath); + added.putExtra(FileDownloader.EXTRA_FILE_PATH, FileStorageUtils.getSavePath(account.name) + + remotePath); mService.sendStickyBroadcast(added); } /** - * TODO review this method when "folder synchronization" replaces "folder download"; this is a fast and ugly - * patch. + * TODO review this method when "folder synchronization" replaces "folder download"; + * this is a fast and ugly patch. */ - private void sendBroadcastFinishedSyncFolder(Account account, String remotePath, boolean success) { + private void sendBroadcastFinishedSyncFolder(Account account, String remotePath, + boolean success) { Intent finished = new Intent(FileDownloader.getDownloadFinishMessage()); finished.putExtra(FileDownloader.ACCOUNT_NAME, account.name); finished.putExtra(FileDownloader.EXTRA_REMOTE_PATH, remotePath); - finished.putExtra(FileDownloader.EXTRA_FILE_PATH, FileStorageUtils.getSavePath(account.name) + remotePath); + finished.putExtra(FileDownloader.EXTRA_FILE_PATH, + FileStorageUtils.getSavePath(account.name) + remotePath); finished.putExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, success); mService.sendStickyBroadcast(finished); }