Merge pull request #2038 from nextcloud/enhanceSyncSpeed

Speed up sync
This commit is contained in:
Mario Đanić 2018-03-15 10:35:59 +01:00 committed by GitHub
commit b0af6f5e61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 46 deletions

View file

@ -316,18 +316,15 @@ public class FileDataStorageManager {
/**
* Inserts or updates the list of files contained in a given folder.
* <p/>
* CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
*
* CALLER IS RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
* HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
*
* @param folder
* @param updatedFiles
* @param filesToRemove
*/
public void saveFolder(
OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
) {
public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {
Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size()
+ " children and " + filesToRemove.size() + " files to remove");
@ -337,32 +334,28 @@ public class FileDataStorageManager {
for (OCFile file : updatedFiles) {
ContentValues cv = createContentValueForFile(file, folder);
boolean existsByPath = fileExists(file.getRemotePath());
if (existsByPath || fileExists(file.getFileId())) {
if (fileExists(file.getFileId()) || fileExists(file.getRemotePath())) {
// updating an existing file
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI)
.withValues(cv)
.withSelection(ProviderTableMeta._ID + "=?", new String[]{String.valueOf(file.getFileId())})
.build());
} else {
// adding a new file
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
withValues(cv).build());
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
}
}
// prepare operations to remove files in the given folder
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + AND +
ProviderTableMeta.FILE_PATH + "=?";
String[] whereArgs = null;
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + "=?";
String[] whereArgs;
for (OCFile file : filesToRemove) {
if (file.getParentId() == folder.getFileId()) {
whereArgs = new String[]{mAccount.name, file.getRemotePath()};
if (file.isFolder()) {
operations.add(ContentProviderOperation.newDelete(
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())
).withSelection(where, whereArgs).build());
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()))
.withSelection(where, whereArgs).build());
File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
if (localFolder.exists()) {
@ -370,9 +363,8 @@ public class FileDataStorageManager {
}
} else {
operations.add(ContentProviderOperation.newDelete(
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()
)
).withSelection(where, whereArgs).build());
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()))
.withSelection(where, whereArgs).build());
if (file.isDown()) {
String path = file.getStoragePath();
@ -386,15 +378,15 @@ public class FileDataStorageManager {
// update metadata of folder
ContentValues cv = createContentValueForFile(folder);
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
withValues(cv).
withSelection(ProviderTableMeta._ID + "=?",
new String[]{String.valueOf(folder.getFileId())})
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI)
.withValues(cv)
.withSelection(ProviderTableMeta._ID + "=?", new String[]{String.valueOf(folder.getFileId())})
.build());
// apply operations in batch
ContentProviderResult[] results = null;
Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size()));
try {
if (getContentResolver() != null) {
results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
@ -460,16 +452,12 @@ public class FileDataStorageManager {
private ContentValues createContentValueForFile(OCFile file, OCFile folder) {
ContentValues cv = new ContentValues();
cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
cv.put(
ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
file.getModificationTimestampAtLastSyncForData()
);
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());
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
cv.put(ProviderTableMeta.FILE_ENCRYPTED_NAME, file.getEncryptedFileName());
//cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
if (!file.isFolder()) {

View file

@ -363,8 +363,7 @@ public class RefreshFolderOperation extends RemoteOperation {
remoteFolder.setParentId(mLocalFolder.getParentId());
remoteFolder.setFileId(mLocalFolder.getFileId());
Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath()
+ " changed - starting update of local data ");
Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " changed - starting update of local data ");
List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
mFilesToSyncContents.clear();
@ -372,6 +371,8 @@ public class RefreshFolderOperation extends RemoteOperation {
// if local folder is encrypted, download fresh metadata
DecryptedFolderMetadata metadata;
boolean encryptedAncestor = FileStorageUtils.checkEncryptionStatus(mLocalFolder, mStorageManager);
mLocalFolder.setEncrypted(encryptedAncestor);
if (encryptedAncestor && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
metadata = EncryptionUtils.downloadFolderMetadata(mLocalFolder, getClient(), mContext, mAccount);
} else {
@ -381,6 +382,7 @@ public class RefreshFolderOperation extends RemoteOperation {
// get current data about local contents of the folder to synchronize
List<OCFile> localFiles = mStorageManager.getFolderContent(mLocalFolder, false);
Map<String, OCFile> localFilesMap = new HashMap<String, OCFile>(localFiles.size());
for (OCFile file : localFiles) {
String remotePath = file.getRemotePath();
@ -391,25 +393,26 @@ public class RefreshFolderOperation extends RemoteOperation {
}
// loop to update every child
OCFile remoteFile = null;
OCFile localFile = null;
OCFile updatedFile = null;
OCFile remoteFile;
OCFile localFile;
OCFile updatedFile;
RemoteFile r;
for (int i = 1; i < folderAndFiles.size(); i++) {
/// new OCFile instance with the data from the server
r = (RemoteFile) folderAndFiles.get(i);
remoteFile = FileStorageUtils.fillOCFile(r);
/// new OCFile instance to merge fresh data from server with local state
// new OCFile instance to merge fresh data from server with local state
updatedFile = FileStorageUtils.fillOCFile(r);
updatedFile.setParentId(mLocalFolder.getFileId());
/// retrieve local data for the read file
// localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
// retrieve local data for the read file
localFile = localFilesMap.remove(remoteFile.getRemotePath());
/// add to updatedFile data about LOCAL STATE (not existing in server)
// add to updatedFile data about LOCAL STATE (not existing in server)
updatedFile.setLastSyncDateForProperties(mCurrentSyncTime);
if (localFile != null) {
updatedFile.setFileId(localFile.getFileId());
updatedFile.setAvailableOffline(localFile.isAvailableOffline());
@ -437,17 +440,13 @@ public class RefreshFolderOperation extends RemoteOperation {
updatedFile.setEtag("");
}
/// check and fix, if needed, local storage path
// check and fix, if needed, local storage path
FileStorageUtils.searchForLocalFileInDefaultPath(updatedFile, mAccount);
/// prepare content synchronization for kept-in-sync files
// prepare content synchronization for kept-in-sync files
if (updatedFile.isAvailableOffline()) {
SynchronizeFileOperation operation = new SynchronizeFileOperation(localFile,
remoteFile,
mAccount,
true,
mContext
);
SynchronizeFileOperation operation = new SynchronizeFileOperation(localFile, remoteFile, mAccount, true,
mContext);
mFilesToSyncContents.add(operation);
}
@ -460,6 +459,7 @@ public class RefreshFolderOperation extends RemoteOperation {
.getFilename();
String mimetype = metadata.getFiles().get(updatedFile.getFileName()).getEncrypted().getMimetype();
updatedFile.setFileName(decryptedFileName);
if (mimetype == null || mimetype.isEmpty()) {
updatedFile.setMimetype("application/octet-stream");
} else {
@ -470,7 +470,8 @@ public class RefreshFolderOperation extends RemoteOperation {
}
}
boolean encrypted = FileStorageUtils.checkEncryptionStatus(updatedFile, mStorageManager);
// we parse content, so either the folder itself or its direct parent (which we check) must be encrypted
boolean encrypted = updatedFile.isEncrypted() || mLocalFolder.isEncrypted();
updatedFile.setEncrypted(encrypted);
updatedFiles.add(updatedFile);