Retry backup verify and rename with delay.

fork-5.53.8
Cody Henthorne 2022-08-23 16:21:10 -04:00 zatwierdzone przez Greyson Parrelli
rodzic 7a7c4c28c2
commit 05c16e4c70
2 zmienionych plików z 49 dodań i 8 usunięć

Wyświetl plik

@ -413,7 +413,7 @@ public class FullBackupExporter extends FullBackupBase {
return count;
}
private static long calculateVeryOldStreamLength(@NonNull AttachmentSecret attachmentSecret, @Nullable byte[] random, @NonNull String data) throws IOException {
private static long calculateVeryOldStreamLength(@NonNull AttachmentSecret attachmentSecret, @Nullable byte[] random, @NonNull String data) {
long result = 0;
try (InputStream inputStream = openAttachmentStream(attachmentSecret, random, data)) {
@ -425,6 +425,10 @@ public class FullBackupExporter extends FullBackupBase {
}
} catch (FileNotFoundException e) {
Log.w(TAG, "Missing attachment: " + e.getMessage());
return 0;
} catch (IOException e) {
Log.w(TAG, "Failed to determine stream length", e);
return 0;
}
return result;
@ -708,6 +712,7 @@ public class FullBackupExporter extends FullBackupBase {
public void close() throws IOException {
outputStream.flush();
outputStream.close();
}
}

Wyświetl plik

@ -4,12 +4,14 @@ package org.thoughtcrime.securesms.jobs;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.signal.core.util.Stopwatch;
import org.signal.core.util.ThreadUtil;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.backup.BackupEvent;
@ -27,11 +29,13 @@ import org.thoughtcrime.securesms.service.GenericForegroundService;
import org.thoughtcrime.securesms.service.NotificationController;
import org.thoughtcrime.securesms.util.BackupUtil;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* Backup Job for installs requiring Scoped Storage.
@ -47,6 +51,10 @@ public final class LocalBackupJobApi29 extends BaseJob {
public static final String TEMP_BACKUP_FILE_PREFIX = ".backup";
public static final String TEMP_BACKUP_FILE_SUFFIX = ".tmp";
private static final int MAX_VERIFY_ATTEMPTS = 5;
private static final int MAX_RENAME_ATTEMPTS = 5;
private static final long WAIT_FOR_SCOPED_STORAGE = TimeUnit.SECONDS.toMillis(2);
LocalBackupJobApi29(@NonNull Parameters parameters) {
super(parameters);
}
@ -123,20 +131,17 @@ public final class LocalBackupJobApi29 extends BaseJob {
this::isCanceled);
stopwatch.split("backup-create");
boolean valid = BackupVerifier.verifyFile(context.getContentResolver().openInputStream(temporaryFile.getUri()), backupPassword, finishedEvent.getCount());
boolean valid = verifyBackup(backupPassword, temporaryFile, finishedEvent);
stopwatch.split("backup-verify");
stopwatch.stop(TAG);
EventBus.getDefault().post(finishedEvent);
if (valid) {
if (!temporaryFile.renameTo(fileName)) {
Log.w(TAG, "Failed to rename temp file");
throw new IOException("Renaming temporary backup file failed!");
}
renameBackup(fileName, temporaryFile);
} else {
BackupFileIOError.VERIFICATION_FAILED.postNotification(context);
}
EventBus.getDefault().post(finishedEvent);
} catch (FullBackupExporter.BackupCanceledException e) {
EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.FINISHED, 0, 0));
Log.w(TAG, "Backup cancelled");
@ -164,6 +169,37 @@ public final class LocalBackupJobApi29 extends BaseJob {
}
}
private boolean verifyBackup(String backupPassword, DocumentFile temporaryFile, BackupEvent finishedEvent) {
Boolean valid = null;
int attempts = 0;
while (attempts < MAX_VERIFY_ATTEMPTS && valid == null) {
try {
valid = BackupVerifier.verifyFile(context.getContentResolver().openInputStream(temporaryFile.getUri()), backupPassword, finishedEvent.getCount());
} catch (FileNotFoundException e) {
Log.w(TAG, "Unable to find backup file, attempt: " + (attempts + 1) + "/" + MAX_VERIFY_ATTEMPTS);
ThreadUtil.sleep(WAIT_FOR_SCOPED_STORAGE);
attempts++;
}
}
return valid != null ? valid : false;
}
private void renameBackup(String fileName, DocumentFile temporaryFile) throws IOException {
int attempts = 0;
while (attempts < MAX_RENAME_ATTEMPTS && !temporaryFile.renameTo(fileName)) {
Log.w(TAG, "Unable to rename backup file, attempt: " + (attempts + 1) + "/" + MAX_RENAME_ATTEMPTS);
ThreadUtil.sleep(WAIT_FOR_SCOPED_STORAGE);
attempts++;
}
if (attempts >= MAX_RENAME_ATTEMPTS) {
Log.w(TAG, "Failed to rename temp file");
throw new IOException("Renaming temporary backup file failed!");
}
}
private static void deleteOldTemporaryBackups(@NonNull DocumentFile backupDirectory) {
for (DocumentFile file : backupDirectory.listFiles()) {
if (file.isFile()) {