Finish delta sync functionality for media files

Signed-off-by: Jonas Mayer <jonas.a.mayer@gmx.net>
This commit is contained in:
Jonas Mayer 2024-03-21 13:52:52 +01:00 committed by backportbot[bot]
parent 2220ced6bf
commit 5fb571f4a3
8 changed files with 72 additions and 35 deletions

View File

@ -133,7 +133,12 @@ interface BackgroundJobManager {
fun startImmediateFilesExportJob(files: Collection<OCFile>): LiveData<JobInfo?>
fun schedulePeriodicFilesSyncJob()
fun startImmediateFilesSyncJob(skipCustomFolders: Boolean = false, overridePowerSaving: Boolean = false)
fun startImmediateFilesSyncJob(
overridePowerSaving: Boolean = false,
changedFiles: Array<String> = arrayOf<String>()
)
fun scheduleOfflineSync()
fun scheduleMediaFoldersDetectionJob()

View File

@ -424,10 +424,13 @@ internal class BackgroundJobManagerImpl(
workManager.enqueueUniquePeriodicWork(JOB_PERIODIC_FILES_SYNC, ExistingPeriodicWorkPolicy.REPLACE, request)
}
override fun startImmediateFilesSyncJob(skipCustomFolders: Boolean, overridePowerSaving: Boolean) {
override fun startImmediateFilesSyncJob(
overridePowerSaving: Boolean,
changedFiles: Array<String>
) {
val arguments = Data.Builder()
.putBoolean(FilesSyncWork.SKIP_CUSTOM, skipCustomFolders)
.putBoolean(FilesSyncWork.OVERRIDE_POWER_SAVING, overridePowerSaving)
.putStringArray(FilesSyncWork.CHANGED_FILES, changedFiles)
.build()
val request = oneTimeRequestBuilder(

View File

@ -61,7 +61,11 @@ class ContentObserverWork(
private fun checkAndStartFileSyncJob() {
val syncFolders = syncerFolderProvider.countEnabledSyncedFolders() > 0
if (!powerManagementService.isPowerSavingEnabled && syncFolders) {
backgroundJobManager.startImmediateFilesSyncJob(true, false)
val changedFiles = mutableListOf<String>();
for (uri in params.triggeredContentUris){
changedFiles.add(uri.toString())
}
backgroundJobManager.startImmediateFilesSyncJob(false, changedFiles.toTypedArray())
}
}

View File

@ -118,7 +118,6 @@ class FilesSyncWork(
}
val resources = context.resources
val lightVersion = resources.getBoolean(R.bool.syncedFolder_light)
val skipCustom = inputData.getBoolean(SKIP_CUSTOM, false)
FilesSyncHelper.restartJobsIfNeeded(
uploadsStorageManager,
userAccountManager,
@ -126,19 +125,10 @@ class FilesSyncWork(
powerManagementService
)
// Get changed files from ContentObserverWork or by scanning filesystem
// Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem
val changedFiles = inputData.getStringArray(CHANGED_FILES)
var useForegroundWorker = false
if (changedFiles != null) {
// TODO Handle single files
FilesSyncHelper.insertChangedEntries(skipCustom,syncedFolderProvider,changedFiles)
} else {
useForegroundWorker = true
updateForegroundWorker(5, true)
// Check every file in every synced folder for changes and update filesystemDataProvider database (expensive)
FilesSyncHelper.insertAllDBEntries(skipCustom, syncedFolderProvider)
updateForegroundWorker(50, true)
}
collectChangedFiles(changedFiles)
// Create all the providers we'll need
val filesystemDataProvider = FilesystemDataProvider(contentResolver)
val currentLocale = resources.configuration.locale
@ -150,9 +140,9 @@ class FilesSyncWork(
for ((index, syncedFolder) in syncedFolders.withIndex()) {
updateForegroundWorker(
(50 + (index.toDouble() / syncedFolders.size.toDouble()) * 50).toInt(),
useForegroundWorker
changedFiles.isNullOrEmpty()
)
if (syncedFolder.isEnabled && (!skipCustom || MediaFolderType.CUSTOM != syncedFolder.type)) {
if (syncedFolder.isEnabled && (changedFiles.isNullOrEmpty() || MediaFolderType.CUSTOM != syncedFolder.type)) {
syncFolder(
context,
resources,
@ -169,6 +159,18 @@ class FilesSyncWork(
return result
}
private fun collectChangedFiles(changedFiles: Array<String>?){
if (!changedFiles.isNullOrEmpty()) {
FilesSyncHelper.insertChangedEntries(syncedFolderProvider,changedFiles)
} else {
// Check every file in every synced folder for changes and update filesystemDataProvider database (expensive)
// Potentially needs a long time so use foreground worker
updateForegroundWorker(5, true)
FilesSyncHelper.insertAllDBEntries(syncedFolderProvider)
updateForegroundWorker(50, true)
}
}
@Suppress("LongMethod") // legacy code
private fun syncFolder(
context: Context,

View File

@ -547,7 +547,7 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
}
if (!preferences.isAutoUploadInitialized()) {
backgroundJobManager.startImmediateFilesSyncJob(false, false);
backgroundJobManager.startImmediateFilesSyncJob(false, new String[]{});
preferences.setAutoUploadInit(true);
}

View File

@ -156,9 +156,6 @@ class SyncedFoldersActivity :
@Inject
lateinit var clock: Clock
@Inject
lateinit var backgroundJobManager: BackgroundJobManager
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@ -580,7 +577,7 @@ class SyncedFoldersActivity :
}
}
if (syncedFolderDisplayItem.isEnabled) {
backgroundJobManager.startImmediateFilesSyncJob(skipCustomFolders = false, overridePowerSaving = false)
backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false)
showBatteryOptimizationInfo()
}
}
@ -708,7 +705,7 @@ class SyncedFoldersActivity :
// existing synced folder setup to be updated
syncedFolderProvider.updateSyncFolder(item)
if (item.isEnabled) {
backgroundJobManager.startImmediateFilesSyncJob(skipCustomFolders = false, overridePowerSaving = false)
backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false)
} else {
val syncedFolderInitiatedKey = KEY_SYNCED_FOLDER_INITIATED_PREFIX + item.id
val arbitraryDataProvider =
@ -725,7 +722,7 @@ class SyncedFoldersActivity :
if (storedId != -1L) {
item.id = storedId
if (item.isEnabled) {
backgroundJobManager.startImmediateFilesSyncJob(skipCustomFolders = false, overridePowerSaving = false)
backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false)
} else {
val syncedFolderInitiatedKey = KEY_SYNCED_FOLDER_INITIATED_PREFIX + item.id
arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey)

View File

@ -194,7 +194,7 @@ public class UploadListActivity extends FileActivity {
}
private void refresh() {
backgroundJobManager.startImmediateFilesSyncJob(false, true);
backgroundJobManager.startImmediateFilesSyncJob(true,new String[]{});
if(uploadsStorageManager.getFailedUploads().length > 0){
// retry failed uploads

View File

@ -119,25 +119,51 @@ public final class FilesSyncHelper {
}
}
public static void insertAllDBEntries(boolean skipCustom,
SyncedFolderProvider syncedFolderProvider) {
public static void insertAllDBEntries(SyncedFolderProvider syncedFolderProvider) {
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled() && (!skipCustom || syncedFolder.getType() != MediaFolderType.CUSTOM)) {
if (syncedFolder.isEnabled()) {
insertAllDBEntriesForSyncedFolder(syncedFolder);
}
}
}
public static void insertChangedEntries(boolean skipCustom,
SyncedFolderProvider syncedFolderProvider,
public static void insertChangedEntries(SyncedFolderProvider syncedFolderProvider,
String[] changedFiles) {
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled() && (!skipCustom || syncedFolder.getType() != MediaFolderType.CUSTOM)) {
insertAllDBEntriesForSyncedFolder(syncedFolder);
final ContentResolver contentResolver = MainApp.getAppContext().getContentResolver();
final FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver);
for (String changedFileURI : changedFiles){
String changedFile = getFileFromURI(changedFileURI);
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled() && syncedFolder.containsFile(changedFile)){
File file = new File(changedFile);
filesystemDataProvider.storeOrUpdateFileValue(changedFile,
file.lastModified(),file.isDirectory(),
syncedFolder);
break;
}
}
}
}
private static String getFileFromURI(String uri){
final Context context = MainApp.getAppContext();
Cursor cursor;
int column_index_data;
String filePath = null;
String[] projection = {MediaStore.MediaColumns.DATA};
cursor = context.getContentResolver().query(Uri.parse(uri), projection, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
filePath = cursor.getString(column_index_data);
cursor.close();
}
return filePath;
}
private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder) {
final Context context = MainApp.getAppContext();
final ContentResolver contentResolver = context.getContentResolver();