From 9d490aaab22f78311e29959b469016f31f1800cb Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Tue, 22 Oct 2013 12:48:58 +0200 Subject: [PATCH] Grant consistency of size of folders with every update operation --- .../datamodel/FileDataStorageManager.java | 45 ++++++------ .../providers/FileContentProvider.java | 70 ++++++++++++------- .../android/syncadapter/FileSyncAdapter.java | 2 +- 3 files changed, 71 insertions(+), 46 deletions(-) diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index 7e5e935a1f..9a4ae4b770 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -233,10 +233,8 @@ public class FileDataStorageManager { if (file.isFolder()) { updateFolderSize(file.getFileId()); - if (file.needsUpdatingWhileSaving()) { - for (OCFile f : getFolderContent(file)) - saveFile(f); - } + } else { + updateFolderSize(file.getParentId()); } return overriden; @@ -255,7 +253,6 @@ public class FileDataStorageManager { Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove"); ArrayList operations = new ArrayList(updatedFiles.size()); - long folderSize = 0; // prepare operations to insert or update files to save in the given folder for (OCFile file : updatedFiles) { @@ -264,7 +261,6 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData()); cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); - folderSize += file.getFileLength(); cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype()); cv.put(ProviderTableMeta.FILE_NAME, file.getFileName()); //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId()); @@ -350,7 +346,7 @@ public class FileDataStorageManager { cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp()); cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData()); cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp()); - cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, folderSize); + cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0); // FileContentProvider calculates the right size cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype()); cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName()); cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId()); @@ -405,6 +401,8 @@ public class FileDataStorageManager { } } + updateFolderSize(folder.getFileId()); + } @@ -412,20 +410,25 @@ public class FileDataStorageManager { * * @param id */ - public void updateFolderSize(long id) { - if (getContentResolver() != null) { - getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR, null, - ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(id) }); - } else { - try { - getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR, null, - ProviderTableMeta._ID + "=?", - new String[] { String.valueOf(id) }); - - } catch (RemoteException e) { - Log_OC.e(TAG, "Exception in update of folder size through compatibility patch " + e.getMessage()); + private void updateFolderSize(long id) { + if (id > FileDataStorageManager.ROOT_PARENT_ID) { + Log_OC.d(TAG, "Updating size of " + id); + if (getContentResolver() != null) { + getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR, null, + ProviderTableMeta._ID + "=?", + new String[] { String.valueOf(id) }); + } else { + try { + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR, null, + ProviderTableMeta._ID + "=?", + new String[] { String.valueOf(id) }); + + } catch (RemoteException e) { + Log_OC.e(TAG, "Exception in update of folder size through compatibility patch " + e.getMessage()); + } } + } else { + Log_OC.e(TAG, "not updating size for folder " + id); } } @@ -450,6 +453,7 @@ public class FileDataStorageManager { } else { getContentResolver().delete(file_uri, where, whereArgs); } + updateFolderSize(file.getParentId()); } if (removeLocalCopy && file.isDown()) { boolean success = new File(file.getStoragePath()).delete(); @@ -489,6 +493,7 @@ public class FileDataStorageManager { } else { getContentResolver().delete(folder_uri, where, whereArgs); } + updateFolderSize(folder.getParentId()); } private void removeLocalFolder(File folder) { diff --git a/src/com/owncloud/android/providers/FileContentProvider.java b/src/com/owncloud/android/providers/FileContentProvider.java index 8673d4f31d..c98bf3a914 100644 --- a/src/com/owncloud/android/providers/FileContentProvider.java +++ b/src/com/owncloud/android/providers/FileContentProvider.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.HashMap; import com.owncloud.android.Log_OC; +import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.db.ProviderMeta; import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; @@ -301,17 +302,6 @@ public class FileContentProvider extends ContentProvider { // DB case_sensitive db.execSQL("PRAGMA case_sensitive_like = true"); Cursor c = sqlQuery.query(db, projection, selection, selectionArgs, null, null, order); - if (mUriMatcher.match(uri) == DIRECTORY && c != null && c.moveToFirst()) { - long size = 0; - while (!c.isAfterLast()) { - size += c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)); - c.moveToNext(); - } - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, size); - db.update(ProviderTableMeta.DB_NAME, cv, ProviderTableMeta._ID + "=?", new String[] {uri.getPathSegments().get(1)}); - } - c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @@ -346,21 +336,51 @@ public class FileContentProvider extends ContentProvider { private int updateFolderSize(SQLiteDatabase db, String folderId) { int count = 0; - Uri selectUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId); - String[] selectProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH }; - String selectWhere = ProviderTableMeta.FILE_PARENT + "=?"; - String updateWhere = ProviderTableMeta._ID + "=?"; String [] whereArgs = new String[] { folderId }; - Cursor childrenLengths = query(db, selectUri, selectProjection, selectWhere, whereArgs, null); - if (childrenLengths != null && childrenLengths.moveToFirst()) { - long size = 0; - while (!childrenLengths.isAfterLast()) { - size += childrenLengths.getLong(childrenLengths.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)); - childrenLengths.moveToNext(); + + // read current size saved for the folder + long folderSize = 0; + long folderParentId = -1; + Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId); + String[] folderProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH, ProviderTableMeta.FILE_PARENT}; + String folderWhere = ProviderTableMeta._ID + "=?"; + Cursor folderCursor = query(db, selectFolderUri, folderProjection, folderWhere, whereArgs, null); + if (folderCursor != null && folderCursor.moveToFirst()) { + folderSize = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));; + folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));; + } + folderCursor.close(); + + // read and sum sizes of children + long childrenSize = 0; + Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId); + String[] childrenProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH, ProviderTableMeta.FILE_PARENT}; + String childrenWhere = ProviderTableMeta.FILE_PARENT + "=?"; + Cursor childrenCursor = query(db, selectChildrenUri, childrenProjection, childrenWhere, whereArgs, null); + if (childrenCursor != null && childrenCursor.moveToFirst()) { + while (!childrenCursor.isAfterLast()) { + childrenSize += childrenCursor.getLong(childrenCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH)); + childrenCursor.moveToNext(); } + } + childrenCursor.close(); + + // update if needed + if (folderSize != childrenSize) { + Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize); ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, size); - count = db.update(ProviderTableMeta.DB_NAME, cv, updateWhere, whereArgs); + cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize); + count = db.update(ProviderTableMeta.DB_NAME, cv, folderWhere, whereArgs); + + // propagate update until root + if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) { + Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId); + updateFolderSize(db, String.valueOf(folderParentId)); + } else { + Log_OC.d("FileContentProvider", "NOT propagating to " + folderParentId); + } + } else { + Log_OC.d("FileContentProvider", "NOT updating, sizes are " + folderSize + " and " + childrenSize); } return count; } @@ -368,7 +388,7 @@ public class FileContentProvider extends ContentProvider { @Override public ContentProviderResult[] applyBatch (ArrayList operations) throws OperationApplicationException { - //Log.d(TAG, "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" ); + Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" ); ContentProviderResult[] results = new ContentProviderResult[operations.size()]; int i=0; @@ -383,7 +403,7 @@ public class FileContentProvider extends ContentProvider { } finally { db.endTransaction(); } - //Log.d(TAG, "applied batch in provider " + this); + Log_OC.d("FileContentProvider", "applied batch in provider " + this); return results; } diff --git a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java index 2aab92226f..04dfbdd642 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java @@ -320,7 +320,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { if(syncDown) { synchronizeFolder(newFile); // update the size of the parent folder again after recursive synchronization - getStorageManager().updateFolderSize(parent.getFileId()); + //getStorageManager().updateFolderSize(parent.getFileId()); sendStickyBroadcast(true, parent.getRemotePath(), null); // notify again to refresh size in UI } }