* Copyright (C) 2012-2013 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
import java.util.List;
import java.util.Vector;
+import com.owncloud.android.DisplayUtils;
+import com.owncloud.android.Log_OC;
import com.owncloud.android.db.ProviderMeta;
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
import com.owncloud.android.utils.FileStorageUtils;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
-import android.util.Log;
public class FileDataStorageManager implements DataStorageManager {
private ContentResolver mContentResolver;
private ContentProviderClient mContentProvider;
private Account mAccount;
-
+
private static String TAG = "FileDataStorageManager";
-
+
public FileDataStorageManager(Account account, ContentResolver cr) {
mContentProvider = null;
mContentResolver = cr;
return file;
}
-
+
private OCFile createRootDir() {
OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
file.setMimetype("DIR");
c.close();
return file;
}
-
+
public OCFile getFileByLocalPath(String path) {
Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
OCFile file = null;
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
- if (file.getParentId() != 0)
+ if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
if (!file.isDirectory())
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
+ cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
boolean sameRemotePath = fileExists(file.getRemotePath());
+ boolean changesSizeOfAncestors = false;
if (sameRemotePath ||
- fileExists(file.getFileId()) ) { // for renamed files; no more delete and create
-
+ fileExists(file.getFileId()) ) { // for renamed files; no more delete and create
+
+ OCFile oldFile = null;
if (sameRemotePath) {
- OCFile oldFile = getFileByPath(file.getRemotePath());
+ oldFile = getFileByPath(file.getRemotePath());
file.setFileId(oldFile.getFileId());
+ } else {
+ oldFile = getFileById(file.getFileId());
}
+ changesSizeOfAncestors = (oldFile.getFileLength() != file.getFileLength());
overriden = true;
if (getContentResolver() != null) {
cv, ProviderTableMeta._ID + "=?",
new String[] { String.valueOf(file.getFileId()) });
} catch (RemoteException e) {
- Log.e(TAG,
+ Log_OC.e(TAG,
"Fail to insert insert file to database "
+ e.getMessage());
}
}
} else {
+ changesSizeOfAncestors = true;
Uri result_uri = null;
if (getContentResolver() != null) {
result_uri = getContentResolver().insert(
result_uri = getContentProvider().insert(
ProviderTableMeta.CONTENT_URI_FILE, cv);
} catch (RemoteException e) {
- Log.e(TAG,
+ Log_OC.e(TAG,
"Fail to insert insert file to database "
+ e.getMessage());
}
long new_id = Long.parseLong(result_uri.getPathSegments()
.get(1));
file.setFileId(new_id);
- }
+ }
}
- if (file.isDirectory() && file.needsUpdatingWhileSaving())
- for (OCFile f : getDirectoryContent(file))
- saveFile(f);
-
+ if (file.isDirectory()) {
+ calculateFolderSize(file.getFileId());
+ if (file.needsUpdatingWhileSaving()) {
+ for (OCFile f : getDirectoryContent(file))
+ saveFile(f);
+ }
+ }
+
+ if (changesSizeOfAncestors || file.isDirectory()) {
+ updateSizesToTheRoot(file.getParentId());
+ }
+
return overriden;
}
@Override
public void saveFiles(List<OCFile> files) {
-
+
Iterator<OCFile> filesIt = files.iterator();
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(files.size());
OCFile file = null;
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
- if (file.getParentId() != 0)
+ if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
if (!file.isDirectory())
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
+ cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
if (fileExists(file.getRemotePath())) {
OCFile oldFile = getFileByPath(file.getRemotePath());
file.setFileId(oldFile.getFileId());
+
+ if (file.isDirectory()) {
+ cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
+ file.setFileLength(oldFile.getFileLength());
+ }
+
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
withValues(cv).
withSelection( ProviderTableMeta._ID + "=?",
- new String[] { String.valueOf(file.getFileId()) })
- .build());
-
+ new String[] { String.valueOf(file.getFileId()) })
+ .build());
+
} else if (fileExists(file.getFileId())) {
- OCFile oldFile = getFileById(file.getFileId());
- if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
- file.setStoragePath(oldFile.getStoragePath());
- if (!file.isDirectory());
- cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+ OCFile oldFile = getFileById(file.getFileId());
+ if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
+ file.setStoragePath(oldFile.getStoragePath());
+
+ if (!file.isDirectory())
+ cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+ else {
+ cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
+ file.setFileLength(oldFile.getFileLength());
+ }
+
+ operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
+ withValues(cv).
+ withSelection( ProviderTableMeta._ID + "=?",
+ new String[] { String.valueOf(file.getFileId()) })
+ .build());
- operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
- withValues(cv).
- withSelection( ProviderTableMeta._ID + "=?",
- new String[] { String.valueOf(file.getFileId()) })
- .build());
-
} else {
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
}
}
-
+
// apply operations in batch
ContentProviderResult[] results = null;
try {
if (getContentResolver() != null) {
results = getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
-
+
} else {
results = getContentProvider().applyBatch(operations);
}
-
+
} catch (OperationApplicationException e) {
- Log.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
-
+ Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
+
} catch (RemoteException e) {
- Log.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
+ Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
}
-
+
// update new id in file objects for insertions
if (results != null) {
long newId;
if (results[i].uri != null) {
newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
files.get(i).setFileId(newId);
- //Log.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
+ //Log_OC.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
}
}
}
}
}
-
+
public void setAccount(Account account) {
mAccount = account;
}
public ContentProviderClient getContentProvider() {
return mContentProvider;
}
-
+
@Override
public Vector<OCFile> getDirectoryContent(OCFile f) {
- Vector<OCFile> ret = new Vector<OCFile>();
if (f != null && f.isDirectory() && f.getFileId() != -1) {
+ return getDirectoryContent(f.getFileId());
- Uri req_uri = Uri.withAppendedPath(
- ProviderTableMeta.CONTENT_URI_DIR,
- String.valueOf(f.getFileId()));
- Cursor c = null;
+ } else {
+ return new Vector<OCFile>();
+ }
+ }
- if (getContentProvider() != null) {
- try {
- c = getContentProvider().query(req_uri, null,
- ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
- new String[] { mAccount.name }, null);
- } catch (RemoteException e) {
- Log.e(TAG, e.getMessage());
- return ret;
- }
- } else {
- c = getContentResolver().query(req_uri, null,
- ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
- new String[] { mAccount.name }, null);
- }
+ private Vector<OCFile> getDirectoryContent(long parentId) {
- if (c.moveToFirst()) {
- do {
- OCFile child = createFileInstance(c);
- ret.add(child);
- } while (c.moveToNext());
+ Vector<OCFile> ret = new Vector<OCFile>();
+
+ Uri req_uri = Uri.withAppendedPath(
+ ProviderTableMeta.CONTENT_URI_DIR,
+ String.valueOf(parentId));
+ Cursor c = null;
+
+ if (getContentProvider() != null) {
+ try {
+ c = getContentProvider().query(req_uri, null,
+ ProviderTableMeta.FILE_PARENT + "=?" ,
+ new String[] { String.valueOf(parentId)}, null);
+ } catch (RemoteException e) {
+ Log_OC.e(TAG, e.getMessage());
+ return ret;
}
+ } else {
+ c = getContentResolver().query(req_uri, null,
+ ProviderTableMeta.FILE_PARENT + "=?" ,
+ new String[] { String.valueOf(parentId)}, null);
+ }
- c.close();
-
- Collections.sort(ret);
-
+ if (c.moveToFirst()) {
+ do {
+ OCFile child = createFileInstance(c);
+ ret.add(child);
+ } while (c.moveToNext());
}
+
+ c.close();
+
+ Collections.sort(ret);
+
return ret;
}
+
+
private boolean fileExists(String cmp_key, String value) {
Cursor c;
cmp_key + "=? AND "
+ ProviderTableMeta.FILE_ACCOUNT_OWNER
+ "=?",
- new String[] { value, mAccount.name }, null);
+ new String[] { value, mAccount.name }, null);
} else {
try {
c = getContentProvider().query(
null,
cmp_key + "=? AND "
+ ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",
- new String[] { value, mAccount.name }, null);
+ new String[] { value, mAccount.name }, null);
} catch (RemoteException e) {
- Log.e(TAG,
+ Log_OC.e(TAG,
"Couldn't determine file existance, assuming non existance: "
+ e.getMessage());
return false;
key + "=? AND "
+ ProviderTableMeta.FILE_ACCOUNT_OWNER
+ "=?",
- new String[] { value, mAccount.name }, null);
+ new String[] { value, mAccount.name }, null);
} else {
try {
c = getContentProvider().query(
ProviderTableMeta.CONTENT_URI,
null,
key + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER
- + "=?", new String[] { value, mAccount.name },
+ + "=?", new String[] { value, mAccount.name },
null);
} catch (RemoteException e) {
- Log.e(TAG, "Could not get file details: " + e.getMessage());
+ Log_OC.e(TAG, "Could not get file details: " + e.getMessage());
c = null;
}
}
file.setLastSyncDateForData(c.getLong(c.
getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
file.setKeepInSync(c.getInt(
- c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
+ c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
+ file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
+
}
return file;
}
-
+
@Override
public void removeFile(OCFile file, boolean removeLocalCopy) {
Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
if (getContentProvider() != null) {
try {
getContentProvider().delete(file_uri,
- ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
- new String[]{mAccount.name});
+ ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
+ new String[]{mAccount.name});
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
getContentResolver().delete(file_uri,
- ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
- new String[]{mAccount.name});
+ ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
+ new String[]{mAccount.name});
}
if (file.isDown() && removeLocalCopy) {
new File(file.getStoragePath()).delete();
f.delete();
}
}
+
+ if (file.getFileLength() > 0) {
+ updateSizesToTheRoot(file.getParentId());
+ }
}
@Override
if (removeDBData) {
removeFile(dir, true);
}
+
+ if (dir.getFileLength() > 0) {
+ updateSizesToTheRoot(dir.getParentId());
+ }
}
}
-
-
+
+
/**
* Updates database for a folder that was moved to a different location.
*
@Override
public void moveDirectory(OCFile dir, String newPath) {
// TODO check newPath
-
+
if (dir != null && dir.isDirectory() && dir.fileExists() && !dir.getFileName().equals(OCFile.PATH_SEPARATOR)) {
/// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
Cursor c = null;
if (getContentProvider() != null) {
try {
c = getContentProvider().query(ProviderTableMeta.CONTENT_URI,
- null,
- ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
- new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
+ null,
+ ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
+ new String[] { mAccount.name, dir.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
} catch (RemoteException e) {
- Log.e(TAG, e.getMessage());
+ Log_OC.e(TAG, e.getMessage());
}
} else {
c = getContentResolver().query(ProviderTableMeta.CONTENT_URI,
- null,
- ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ?",
- new String[] { mAccount.name, dir.getRemotePath() + "%" }, null);
+ null,
+ ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
+ new String[] { mAccount.name, dir.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
}
/// 2. prepare a batch of update operations to change all the descendants
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
}
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
- withValues(cv).
- withSelection( ProviderTableMeta._ID + "=?",
- new String[] { String.valueOf(child.getFileId()) })
- .build());
+ withValues(cv).
+ withSelection( ProviderTableMeta._ID + "=?",
+ new String[] { String.valueOf(child.getFileId()) })
+ .build());
} while (c.moveToNext());
}
c.close();
-
+
/// 3. apply updates in batch
try {
if (getContentResolver() != null) {
getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
-
+
} else {
getContentProvider().applyBatch(operations);
}
-
+
} catch (OperationApplicationException e) {
- Log.e(TAG, "Fail to update descendants of " + dir.getFileId() + " in database", e);
-
+ Log_OC.e(TAG, "Fail to update descendants of " + dir.getFileId() + " in database", e);
+
} catch (RemoteException e) {
- Log.e(TAG, "Fail to update desendants of " + dir.getFileId() + " in database", e);
+ Log_OC.e(TAG, "Fail to update desendants of " + dir.getFileId() + " in database", e);
}
-
+
}
}
return ret;
}
+ /**
+ * Calculate and save the folderSize on DB
+ * @param id
+ */
+ @Override
+ public void calculateFolderSize(long id) {
+ long folderSize = 0;
+
+ Vector<OCFile> files = getDirectoryContent(id);
+
+ for (OCFile f: files)
+ {
+ folderSize = folderSize + f.getFileLength();
+ }
+
+ updateSize(id, folderSize);
+ }
+
+ /**
+ * Update the size value of an OCFile in DB
+ */
+ private int updateSize(long id, long size) {
+ ContentValues cv = new ContentValues();
+ cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, size);
+ int result = -1;
+ if (getContentResolver() != null) {
+ result = getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?",
+ new String[] { String.valueOf(id) });
+ } else {
+ try {
+ result = getContentProvider().update(ProviderTableMeta.CONTENT_URI, cv, ProviderTableMeta._ID + "=?",
+ new String[] { String.valueOf(id) });
+ } catch (RemoteException e) {
+ Log_OC.e(TAG,"Fail to update size column into database " + e.getMessage());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Update the size of a subtree of folder from a file to the root
+ * @param parentId: parent of the file
+ */
+ private void updateSizesToTheRoot(long parentId) {
+
+ OCFile file;
+
+ while (parentId != DataStorageManager.ROOT_PARENT_ID) {
+
+ Log_OC.d(TAG, "parent = " + parentId);
+ // Update the size of the parent
+ calculateFolderSize(parentId);
+
+ // search the next parent
+ file = getFileById(parentId);
+ parentId = file.getParentId();
+
+ }
+
+ }
+
}