1 /* ownCloud Android client application
2 * Copyright (C) 2012 Bartek Przybylski
3 * Copyright (C) 2012-2013 ownCloud Inc.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2,
7 * as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 package com
.owncloud
.android
.datamodel
;
22 import java
.util
.ArrayList
;
23 import java
.util
.Collections
;
24 import java
.util
.Iterator
;
25 import java
.util
.List
;
26 import java
.util
.Vector
;
28 import com
.owncloud
.android
.DisplayUtils
;
29 import com
.owncloud
.android
.Log_OC
;
30 import com
.owncloud
.android
.db
.ProviderMeta
;
31 import com
.owncloud
.android
.db
.ProviderMeta
.ProviderTableMeta
;
32 import com
.owncloud
.android
.utils
.FileStorageUtils
;
34 import android
.accounts
.Account
;
35 import android
.content
.ContentProviderClient
;
36 import android
.content
.ContentProviderOperation
;
37 import android
.content
.ContentProviderResult
;
38 import android
.content
.ContentResolver
;
39 import android
.content
.ContentValues
;
40 import android
.content
.OperationApplicationException
;
41 import android
.database
.Cursor
;
42 import android
.net
.Uri
;
43 import android
.os
.RemoteException
;
45 public class FileDataStorageManager
{
47 public static final int ROOT_PARENT_ID
= 0;
49 private ContentResolver mContentResolver
;
50 private ContentProviderClient mContentProvider
;
51 private Account mAccount
;
53 private static String TAG
= "FileDataStorageManager";
55 public FileDataStorageManager(Account account
, ContentResolver cr
) {
56 mContentProvider
= null
;
57 mContentResolver
= cr
;
61 public FileDataStorageManager(Account account
, ContentProviderClient cp
) {
62 mContentProvider
= cp
;
63 mContentResolver
= null
;
68 public OCFile
getFileByPath(String path
) {
69 Cursor c
= getCursorForValue(ProviderTableMeta
.FILE_PATH
, path
);
71 if (c
.moveToFirst()) {
72 file
= createFileInstance(c
);
75 if (file
== null
&& OCFile
.PATH_SEPARATOR
.equals(path
)) {
76 return createRootDir(); // root should always exist
82 private OCFile
createRootDir() {
83 OCFile file
= new OCFile(OCFile
.PATH_SEPARATOR
);
84 file
.setMimetype("DIR");
85 file
.setParentId(FileDataStorageManager
.ROOT_PARENT_ID
);
90 public OCFile
getFileById(long id
) {
91 Cursor c
= getCursorForValue(ProviderTableMeta
._ID
, String
.valueOf(id
));
93 if (c
.moveToFirst()) {
94 file
= createFileInstance(c
);
100 public OCFile
getFileByLocalPath(String path
) {
101 Cursor c
= getCursorForValue(ProviderTableMeta
.FILE_STORAGE_PATH
, path
);
103 if (c
.moveToFirst()) {
104 file
= createFileInstance(c
);
110 public boolean fileExists(long id
) {
111 return fileExists(ProviderTableMeta
._ID
, String
.valueOf(id
));
114 public boolean fileExists(String path
) {
115 return fileExists(ProviderTableMeta
.FILE_PATH
, path
);
118 public boolean saveFile(OCFile file
) {
119 boolean overriden
= false
;
120 ContentValues cv
= new ContentValues();
121 cv
.put(ProviderTableMeta
.FILE_MODIFIED
, file
.getModificationTimestamp());
122 cv
.put(ProviderTableMeta
.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA
, file
.getModificationTimestampAtLastSyncForData());
123 cv
.put(ProviderTableMeta
.FILE_CREATION
, file
.getCreationTimestamp());
124 cv
.put(ProviderTableMeta
.FILE_CONTENT_LENGTH
, file
.getFileLength());
125 cv
.put(ProviderTableMeta
.FILE_CONTENT_TYPE
, file
.getMimetype());
126 cv
.put(ProviderTableMeta
.FILE_NAME
, file
.getFileName());
127 //if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
128 cv
.put(ProviderTableMeta
.FILE_PARENT
, file
.getParentId());
129 cv
.put(ProviderTableMeta
.FILE_PATH
, file
.getRemotePath());
130 if (!file
.isDirectory())
131 cv
.put(ProviderTableMeta
.FILE_STORAGE_PATH
, file
.getStoragePath());
132 cv
.put(ProviderTableMeta
.FILE_ACCOUNT_OWNER
, mAccount
.name
);
133 cv
.put(ProviderTableMeta
.FILE_LAST_SYNC_DATE
, file
.getLastSyncDateForProperties());
134 cv
.put(ProviderTableMeta
.FILE_LAST_SYNC_DATE_FOR_DATA
, file
.getLastSyncDateForData());
135 cv
.put(ProviderTableMeta
.FILE_KEEP_IN_SYNC
, file
.keepInSync() ?
1 : 0);
136 cv
.put(ProviderTableMeta
.FILE_ETAG
, file
.getEtag());
138 boolean sameRemotePath
= fileExists(file
.getRemotePath());
139 boolean changesSizeOfAncestors
= false
;
140 if (sameRemotePath
||
141 fileExists(file
.getFileId()) ) { // for renamed files; no more delete and create
143 OCFile oldFile
= null
;
144 if (sameRemotePath
) {
145 oldFile
= getFileByPath(file
.getRemotePath());
146 file
.setFileId(oldFile
.getFileId());
148 oldFile
= getFileById(file
.getFileId());
150 changesSizeOfAncestors
= (oldFile
.getFileLength() != file
.getFileLength());
153 if (getContentResolver() != null
) {
154 getContentResolver().update(ProviderTableMeta
.CONTENT_URI
, cv
,
155 ProviderTableMeta
._ID
+ "=?",
156 new String
[] { String
.valueOf(file
.getFileId()) });
159 getContentProvider().update(ProviderTableMeta
.CONTENT_URI
,
160 cv
, ProviderTableMeta
._ID
+ "=?",
161 new String
[] { String
.valueOf(file
.getFileId()) });
162 } catch (RemoteException e
) {
164 "Fail to insert insert file to database "
169 changesSizeOfAncestors
= true
;
170 Uri result_uri
= null
;
171 if (getContentResolver() != null
) {
172 result_uri
= getContentResolver().insert(
173 ProviderTableMeta
.CONTENT_URI_FILE
, cv
);
176 result_uri
= getContentProvider().insert(
177 ProviderTableMeta
.CONTENT_URI_FILE
, cv
);
178 } catch (RemoteException e
) {
180 "Fail to insert insert file to database "
184 if (result_uri
!= null
) {
185 long new_id
= Long
.parseLong(result_uri
.getPathSegments()
187 file
.setFileId(new_id
);
191 if (file
.isDirectory()) {
192 calculateFolderSize(file
.getFileId());
193 if (file
.needsUpdatingWhileSaving()) {
194 for (OCFile f
: getDirectoryContent(file
))
199 if (changesSizeOfAncestors
|| file
.isDirectory()) {
200 updateSizesToTheRoot(file
.getParentId());
207 public void saveFiles(List
<OCFile
> files
) {
209 Iterator
<OCFile
> filesIt
= files
.iterator();
210 ArrayList
<ContentProviderOperation
> operations
= new ArrayList
<ContentProviderOperation
>(files
.size());
213 // prepare operations to perform
214 while (filesIt
.hasNext()) {
215 file
= filesIt
.next();
216 ContentValues cv
= new ContentValues();
217 cv
.put(ProviderTableMeta
.FILE_MODIFIED
, file
.getModificationTimestamp());
218 cv
.put(ProviderTableMeta
.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA
, file
.getModificationTimestampAtLastSyncForData());
219 cv
.put(ProviderTableMeta
.FILE_CREATION
, file
.getCreationTimestamp());
220 cv
.put(ProviderTableMeta
.FILE_CONTENT_LENGTH
, file
.getFileLength());
221 cv
.put(ProviderTableMeta
.FILE_CONTENT_TYPE
, file
.getMimetype());
222 cv
.put(ProviderTableMeta
.FILE_NAME
, file
.getFileName());
223 if (file
.getParentId() != FileDataStorageManager
.ROOT_PARENT_ID
)
224 cv
.put(ProviderTableMeta
.FILE_PARENT
, file
.getParentId());
225 cv
.put(ProviderTableMeta
.FILE_PATH
, file
.getRemotePath());
226 if (!file
.isDirectory())
227 cv
.put(ProviderTableMeta
.FILE_STORAGE_PATH
, file
.getStoragePath());
228 cv
.put(ProviderTableMeta
.FILE_ACCOUNT_OWNER
, mAccount
.name
);
229 cv
.put(ProviderTableMeta
.FILE_LAST_SYNC_DATE
, file
.getLastSyncDateForProperties());
230 cv
.put(ProviderTableMeta
.FILE_LAST_SYNC_DATE_FOR_DATA
, file
.getLastSyncDateForData());
231 cv
.put(ProviderTableMeta
.FILE_KEEP_IN_SYNC
, file
.keepInSync() ?
1 : 0);
232 cv
.put(ProviderTableMeta
.FILE_ETAG
, file
.getEtag());
234 if (fileExists(file
.getRemotePath())) {
235 OCFile oldFile
= getFileByPath(file
.getRemotePath());
236 file
.setFileId(oldFile
.getFileId());
238 if (file
.isDirectory()) {
239 cv
.put(ProviderTableMeta
.FILE_CONTENT_LENGTH
, oldFile
.getFileLength());
240 file
.setFileLength(oldFile
.getFileLength());
243 operations
.add(ContentProviderOperation
.newUpdate(ProviderTableMeta
.CONTENT_URI
).
245 withSelection( ProviderTableMeta
._ID
+ "=?",
246 new String
[] { String
.valueOf(file
.getFileId()) })
249 } else if (fileExists(file
.getFileId())) {
250 OCFile oldFile
= getFileById(file
.getFileId());
251 if (file
.getStoragePath() == null
&& oldFile
.getStoragePath() != null
)
252 file
.setStoragePath(oldFile
.getStoragePath());
254 if (!file
.isDirectory())
255 cv
.put(ProviderTableMeta
.FILE_STORAGE_PATH
, file
.getStoragePath());
257 cv
.put(ProviderTableMeta
.FILE_CONTENT_LENGTH
, oldFile
.getFileLength());
258 file
.setFileLength(oldFile
.getFileLength());
261 operations
.add(ContentProviderOperation
.newUpdate(ProviderTableMeta
.CONTENT_URI
).
263 withSelection( ProviderTableMeta
._ID
+ "=?",
264 new String
[] { String
.valueOf(file
.getFileId()) })
268 operations
.add(ContentProviderOperation
.newInsert(ProviderTableMeta
.CONTENT_URI
).withValues(cv
).build());
272 // apply operations in batch
273 ContentProviderResult
[] results
= null
;
275 if (getContentResolver() != null
) {
276 results
= getContentResolver().applyBatch(ProviderMeta
.AUTHORITY_FILES
, operations
);
279 results
= getContentProvider().applyBatch(operations
);
282 } catch (OperationApplicationException e
) {
283 Log_OC
.e(TAG
, "Fail to update/insert list of files to database " + e
.getMessage());
285 } catch (RemoteException e
) {
286 Log_OC
.e(TAG
, "Fail to update/insert list of files to database " + e
.getMessage());
289 // update new id in file objects for insertions
290 if (results
!= null
) {
292 for (int i
=0; i
<results
.length
; i
++) {
293 if (results
[i
].uri
!= null
) {
294 newId
= Long
.parseLong(results
[i
].uri
.getPathSegments().get(1));
295 files
.get(i
).setFileId(newId
);
296 //Log_OC.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
301 for (OCFile aFile
: files
) {
302 if (aFile
.isDirectory() && aFile
.needsUpdatingWhileSaving())
303 saveFiles(getDirectoryContent(aFile
));
308 public void setAccount(Account account
) {
312 public Account
getAccount() {
316 public void setContentResolver(ContentResolver cr
) {
317 mContentResolver
= cr
;
320 public ContentResolver
getContentResolver() {
321 return mContentResolver
;
324 public void setContentProvider(ContentProviderClient cp
) {
325 mContentProvider
= cp
;
328 public ContentProviderClient
getContentProvider() {
329 return mContentProvider
;
332 public Vector
<OCFile
> getDirectoryContent(OCFile f
) {
333 if (f
!= null
&& f
.isDirectory() && f
.getFileId() != -1) {
334 return getDirectoryContent(f
.getFileId());
337 return new Vector
<OCFile
>();
341 private Vector
<OCFile
> getDirectoryContent(long parentId
) {
343 Vector
<OCFile
> ret
= new Vector
<OCFile
>();
345 Uri req_uri
= Uri
.withAppendedPath(
346 ProviderTableMeta
.CONTENT_URI_DIR
,
347 String
.valueOf(parentId
));
350 if (getContentProvider() != null
) {
352 c
= getContentProvider().query(req_uri
, null
,
353 ProviderTableMeta
.FILE_PARENT
+ "=?" ,
354 new String
[] { String
.valueOf(parentId
)}, null
);
355 } catch (RemoteException e
) {
356 Log_OC
.e(TAG
, e
.getMessage());
360 c
= getContentResolver().query(req_uri
, null
,
361 ProviderTableMeta
.FILE_PARENT
+ "=?" ,
362 new String
[] { String
.valueOf(parentId
)}, null
);
365 if (c
.moveToFirst()) {
367 OCFile child
= createFileInstance(c
);
369 } while (c
.moveToNext());
374 Collections
.sort(ret
);
381 private boolean fileExists(String cmp_key
, String value
) {
383 if (getContentResolver() != null
) {
384 c
= getContentResolver()
385 .query(ProviderTableMeta
.CONTENT_URI
,
388 + ProviderTableMeta
.FILE_ACCOUNT_OWNER
390 new String
[] { value
, mAccount
.name
}, null
);
393 c
= getContentProvider().query(
394 ProviderTableMeta
.CONTENT_URI
,
397 + ProviderTableMeta
.FILE_ACCOUNT_OWNER
+ "=?",
398 new String
[] { value
, mAccount
.name
}, null
);
399 } catch (RemoteException e
) {
401 "Couldn't determine file existance, assuming non existance: "
406 boolean retval
= c
.moveToFirst();
411 private Cursor
getCursorForValue(String key
, String value
) {
413 if (getContentResolver() != null
) {
414 c
= getContentResolver()
415 .query(ProviderTableMeta
.CONTENT_URI
,
418 + ProviderTableMeta
.FILE_ACCOUNT_OWNER
420 new String
[] { value
, mAccount
.name
}, null
);
423 c
= getContentProvider().query(
424 ProviderTableMeta
.CONTENT_URI
,
426 key
+ "=? AND " + ProviderTableMeta
.FILE_ACCOUNT_OWNER
427 + "=?", new String
[] { value
, mAccount
.name
},
429 } catch (RemoteException e
) {
430 Log_OC
.e(TAG
, "Could not get file details: " + e
.getMessage());
437 private OCFile
createFileInstance(Cursor c
) {
440 file
= new OCFile(c
.getString(c
441 .getColumnIndex(ProviderTableMeta
.FILE_PATH
)));
442 file
.setFileId(c
.getLong(c
.getColumnIndex(ProviderTableMeta
._ID
)));
443 file
.setParentId(c
.getLong(c
444 .getColumnIndex(ProviderTableMeta
.FILE_PARENT
)));
445 file
.setMimetype(c
.getString(c
446 .getColumnIndex(ProviderTableMeta
.FILE_CONTENT_TYPE
)));
447 if (!file
.isDirectory()) {
448 file
.setStoragePath(c
.getString(c
449 .getColumnIndex(ProviderTableMeta
.FILE_STORAGE_PATH
)));
450 if (file
.getStoragePath() == null
) {
451 // try to find existing file and bind it with current account; - with the current update of SynchronizeFolderOperation, this won't be necessary anymore after a full synchronization of the account
452 File f
= new File(FileStorageUtils
.getDefaultSavePathFor(mAccount
.name
, file
));
454 file
.setStoragePath(f
.getAbsolutePath());
455 file
.setLastSyncDateForData(f
.lastModified());
459 file
.setFileLength(c
.getLong(c
460 .getColumnIndex(ProviderTableMeta
.FILE_CONTENT_LENGTH
)));
461 file
.setCreationTimestamp(c
.getLong(c
462 .getColumnIndex(ProviderTableMeta
.FILE_CREATION
)));
463 file
.setModificationTimestamp(c
.getLong(c
464 .getColumnIndex(ProviderTableMeta
.FILE_MODIFIED
)));
465 file
.setModificationTimestampAtLastSyncForData(c
.getLong(c
466 .getColumnIndex(ProviderTableMeta
.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA
)));
467 file
.setLastSyncDateForProperties(c
.getLong(c
468 .getColumnIndex(ProviderTableMeta
.FILE_LAST_SYNC_DATE
)));
469 file
.setLastSyncDateForData(c
.getLong(c
.
470 getColumnIndex(ProviderTableMeta
.FILE_LAST_SYNC_DATE_FOR_DATA
)));
471 file
.setKeepInSync(c
.getInt(
472 c
.getColumnIndex(ProviderTableMeta
.FILE_KEEP_IN_SYNC
)) == 1 ? true
: false
);
473 file
.setEtag(c
.getString(c
.getColumnIndex(ProviderTableMeta
.FILE_ETAG
)));
479 public void removeFile(OCFile file
, boolean removeLocalCopy
) {
480 Uri file_uri
= Uri
.withAppendedPath(ProviderTableMeta
.CONTENT_URI_FILE
, ""+file
.getFileId());
481 if (getContentProvider() != null
) {
483 getContentProvider().delete(file_uri
,
484 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+"=?",
485 new String
[]{mAccount
.name
});
486 } catch (RemoteException e
) {
490 getContentResolver().delete(file_uri
,
491 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+"=?",
492 new String
[]{mAccount
.name
});
494 if (file
.isDown() && removeLocalCopy
) {
495 new File(file
.getStoragePath()).delete();
497 if (file
.isDirectory() && removeLocalCopy
) {
498 File f
= new File(FileStorageUtils
.getDefaultSavePathFor(mAccount
.name
, file
));
499 if (f
.exists() && f
.isDirectory() && (f
.list() == null
|| f
.list().length
== 0)) {
504 if (file
.getFileLength() > 0) {
505 updateSizesToTheRoot(file
.getParentId());
509 public void removeDirectory(OCFile dir
, boolean removeDBData
, boolean removeLocalContent
) {
510 // TODO consider possible failures
511 if (dir
!= null
&& dir
.isDirectory() && dir
.getFileId() != -1) {
512 Vector
<OCFile
> children
= getDirectoryContent(dir
);
513 if (children
.size() > 0) {
515 for (int i
=0; i
<children
.size(); i
++) {
516 child
= children
.get(i
);
517 if (child
.isDirectory()) {
518 removeDirectory(child
, removeDBData
, removeLocalContent
);
521 removeFile(child
, removeLocalContent
);
522 } else if (removeLocalContent
) {
523 if (child
.isDown()) {
524 new File(child
.getStoragePath()).delete();
531 removeFile(dir
, true
);
534 if (dir
.getFileLength() > 0) {
535 updateSizesToTheRoot(dir
.getParentId());
542 * Updates database for a folder that was moved to a different location.
544 * TODO explore better (faster) implementations
545 * TODO throw exceptions up !
547 public void moveDirectory(OCFile dir
, String newPath
) {
548 // TODO check newPath
550 if (dir
!= null
&& dir
.isDirectory() && dir
.fileExists() && !dir
.getFileName().equals(OCFile
.PATH_SEPARATOR
)) {
551 /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
553 if (getContentProvider() != null
) {
555 c
= getContentProvider().query(ProviderTableMeta
.CONTENT_URI
,
557 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+ "=? AND " + ProviderTableMeta
.FILE_PATH
+ " LIKE ? ",
558 new String
[] { mAccount
.name
, dir
.getRemotePath() + "%" }, ProviderTableMeta
.FILE_PATH
+ " ASC ");
559 } catch (RemoteException e
) {
560 Log_OC
.e(TAG
, e
.getMessage());
563 c
= getContentResolver().query(ProviderTableMeta
.CONTENT_URI
,
565 ProviderTableMeta
.FILE_ACCOUNT_OWNER
+ "=? AND " + ProviderTableMeta
.FILE_PATH
+ " LIKE ? ",
566 new String
[] { mAccount
.name
, dir
.getRemotePath() + "%" }, ProviderTableMeta
.FILE_PATH
+ " ASC ");
569 /// 2. prepare a batch of update operations to change all the descendants
570 ArrayList
<ContentProviderOperation
> operations
= new ArrayList
<ContentProviderOperation
>(c
.getCount());
571 int lengthOfOldPath
= dir
.getRemotePath().length();
572 String defaultSavePath
= FileStorageUtils
.getSavePath(mAccount
.name
);
573 int lengthOfOldStoragePath
= defaultSavePath
.length() + lengthOfOldPath
;
574 if (c
.moveToFirst()) {
576 ContentValues cv
= new ContentValues(); // don't take the constructor out of the loop and clear the object
577 OCFile child
= createFileInstance(c
);
578 cv
.put(ProviderTableMeta
.FILE_PATH
, newPath
+ child
.getRemotePath().substring(lengthOfOldPath
));
579 if (child
.getStoragePath() != null
&& child
.getStoragePath().startsWith(defaultSavePath
)) {
580 cv
.put(ProviderTableMeta
.FILE_STORAGE_PATH
, defaultSavePath
+ newPath
+ child
.getStoragePath().substring(lengthOfOldStoragePath
));
582 operations
.add(ContentProviderOperation
.newUpdate(ProviderTableMeta
.CONTENT_URI
).
584 withSelection( ProviderTableMeta
._ID
+ "=?",
585 new String
[] { String
.valueOf(child
.getFileId()) })
587 } while (c
.moveToNext());
591 /// 3. apply updates in batch
593 if (getContentResolver() != null
) {
594 getContentResolver().applyBatch(ProviderMeta
.AUTHORITY_FILES
, operations
);
597 getContentProvider().applyBatch(operations
);
600 } catch (OperationApplicationException e
) {
601 Log_OC
.e(TAG
, "Fail to update descendants of " + dir
.getFileId() + " in database", e
);
603 } catch (RemoteException e
) {
604 Log_OC
.e(TAG
, "Fail to update desendants of " + dir
.getFileId() + " in database", e
);
610 public Vector
<OCFile
> getDirectoryImages(OCFile directory
) {
611 Vector
<OCFile
> ret
= new Vector
<OCFile
>();
612 if (directory
!= null
) {
613 // TODO better implementation, filtering in the access to database (if possible) instead of here
614 Vector
<OCFile
> tmp
= getDirectoryContent(directory
);
615 OCFile current
= null
;
616 for (int i
=0; i
<tmp
.size(); i
++) {
617 current
= tmp
.get(i
);
618 if (current
.isImage()) {
627 * Calculate and save the folderSize on DB
630 public void calculateFolderSize(long id
) {
633 Vector
<OCFile
> files
= getDirectoryContent(id
);
635 for (OCFile f
: files
)
637 folderSize
= folderSize
+ f
.getFileLength();
640 updateSize(id
, folderSize
);
644 * Update the size value of an OCFile in DB
646 private int updateSize(long id
, long size
) {
647 ContentValues cv
= new ContentValues();
648 cv
.put(ProviderTableMeta
.FILE_CONTENT_LENGTH
, size
);
650 if (getContentResolver() != null
) {
651 result
= getContentResolver().update(ProviderTableMeta
.CONTENT_URI
, cv
, ProviderTableMeta
._ID
+ "=?",
652 new String
[] { String
.valueOf(id
) });
655 result
= getContentProvider().update(ProviderTableMeta
.CONTENT_URI
, cv
, ProviderTableMeta
._ID
+ "=?",
656 new String
[] { String
.valueOf(id
) });
657 } catch (RemoteException e
) {
658 Log_OC
.e(TAG
,"Fail to update size column into database " + e
.getMessage());
665 * Update the size of a subtree of folder from a file to the root
666 * @param parentId: parent of the file
668 private void updateSizesToTheRoot(long parentId
) {
672 while (parentId
!= FileDataStorageManager
.ROOT_PARENT_ID
) {
674 // Update the size of the parent
675 calculateFolderSize(parentId
);
677 // search the next parent
678 file
= getFileById(parentId
);
679 parentId
= file
.getParentId();