Add local cache of backup fragment metadata.

This commit is contained in:
Matthew Chen 2018-03-22 11:21:22 -04:00
parent e88f5643f7
commit 61dc2c0249
11 changed files with 63 additions and 66 deletions

View File

@ -171,7 +171,7 @@ NS_ASSUME_NONNULL_BEGIN
[OWSPrimaryStorage.sharedManager.newDatabaseConnection
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[transaction removeAllObjectsInCollection:[OWSBackupManifestItem collection]];
[transaction removeAllObjectsInCollection:[OWSBackupFragment collection]];
}];
}

View File

@ -507,14 +507,14 @@ NS_ASSUME_NONNULL_BEGIN
return;
}
TSAttachmentStream *attachmentStream = object;
if (!attachmentStream.backupRestoreMetadata) {
if (!attachmentStream.lazyRestoreFragment) {
OWSProdLogAndFail(@"%@ Invalid object: %@ in collection:%@",
self.logTag,
[object class],
collection);
return;
}
[recordNames addObject:attachmentStream.backupRestoreMetadata.recordName];
[recordNames addObject:attachmentStream.lazyRestoreFragment.recordName];
}];
}];
return recordNames;
@ -556,13 +556,13 @@ NS_ASSUME_NONNULL_BEGIN
return completion(NO);
}
OWSBackupManifestItem *_Nullable backupRestoreMetadata = attachment.backupRestoreMetadata;
if (!backupRestoreMetadata) {
OWSBackupFragment *_Nullable lazyRestoreFragment = attachment.lazyRestoreFragment;
if (!lazyRestoreFragment) {
DDLogWarn(@"%@ Attachment missing lazy restore metadata.", self.logTag);
return completion(NO);
}
if (backupRestoreMetadata.recordName.length < 1 || backupRestoreMetadata.encryptionKey.length < 1) {
DDLogError(@"%@ Incomplete attachment metadata.", self.logTag);
if (lazyRestoreFragment.recordName.length < 1 || lazyRestoreFragment.encryptionKey.length < 1) {
DDLogError(@"%@ Incomplete lazy restore metadata.", self.logTag);
return completion(NO);
}
@ -575,14 +575,14 @@ NS_ASSUME_NONNULL_BEGIN
return completion(NO);
}
[OWSBackupAPI downloadFileFromCloudWithRecordName:backupRestoreMetadata.recordName
[OWSBackupAPI downloadFileFromCloudWithRecordName:lazyRestoreFragment.recordName
toFileUrl:[NSURL fileURLWithPath:tempFilePath]
success:^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self lazyRestoreAttachment:attachment
backupIO:backupIO
encryptedFilePath:tempFilePath
encryptionKey:backupRestoreMetadata.encryptionKey
encryptionKey:lazyRestoreFragment.encryptionKey
completion:completion];
});
}
@ -634,7 +634,7 @@ NS_ASSUME_NONNULL_BEGIN
return completion(NO);
}
[attachment updateWithBackupRestoreComplete];
[attachment updateWithLazyRestoreComplete];
completion(YES);
}

View File

@ -743,17 +743,16 @@ NS_ASSUME_NONNULL_BEGIN
// this record's metadata.
// * That this record does in fact exist in our CloudKit database.
NSString *lastRecordName = [OWSBackupAPI recordNameForPersistentFileWithFileId:attachmentExport.attachmentId];
OWSBackupManifestItem *_Nullable lastManifestItem =
[OWSBackupManifestItem fetchObjectWithUniqueID:lastRecordName];
if (lastManifestItem && [self.lastValidRecordNames containsObject:lastRecordName]) {
OWSAssert(lastManifestItem.encryptionKey.length > 0);
OWSAssert(lastManifestItem.relativeFilePath.length > 0);
OWSBackupFragment *_Nullable lastBackupFragment = [OWSBackupFragment fetchObjectWithUniqueID:lastRecordName];
if (lastBackupFragment && [self.lastValidRecordNames containsObject:lastRecordName]) {
OWSAssert(lastBackupFragment.encryptionKey.length > 0);
OWSAssert(lastBackupFragment.relativeFilePath.length > 0);
// Recycle the metadata from the last backup's manifest.
OWSBackupEncryptedItem *encryptedItem = [OWSBackupEncryptedItem new];
encryptedItem.encryptionKey = lastManifestItem.encryptionKey;
encryptedItem.encryptionKey = lastBackupFragment.encryptionKey;
attachmentExport.encryptedItem = encryptedItem;
attachmentExport.relativeFilePath = lastManifestItem.relativeFilePath;
attachmentExport.relativeFilePath = lastBackupFragment.relativeFilePath;
OWSBackupExportItem *exportItem = [OWSBackupExportItem new];
exportItem.encryptedItem = attachmentExport.encryptedItem;
@ -814,12 +813,12 @@ NS_ASSUME_NONNULL_BEGIN
[strongSelf.savedAttachmentItems addObject:exportItem];
// Immediately save the record metadata to facilitate export resume.
OWSBackupManifestItem *backupRestoreMetadata = [OWSBackupManifestItem new];
backupRestoreMetadata.recordName = recordName;
backupRestoreMetadata.encryptionKey = exportItem.encryptedItem.encryptionKey;
backupRestoreMetadata.relativeFilePath = attachmentExport.relativeFilePath;
backupRestoreMetadata.uncompressedDataLength = exportItem.uncompressedDataLength;
[backupRestoreMetadata save];
OWSBackupFragment *backupFragment = [OWSBackupFragment new];
backupFragment.recordName = recordName;
backupFragment.encryptionKey = exportItem.encryptedItem.encryptionKey;
backupFragment.relativeFilePath = attachmentExport.relativeFilePath;
backupFragment.uncompressedDataLength = exportItem.uncompressedDataLength;
[backupFragment save];
DDLogVerbose(@"%@ saved attachment: %@ as %@",
self.logTag,
@ -992,11 +991,10 @@ NS_ASSUME_NONNULL_BEGIN
// the latest backup export.
[self.primaryStorage.newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSMutableSet<NSString *> *obsoleteRecordNames = [NSMutableSet new];
[obsoleteRecordNames addObjectsFromArray:[transaction allKeysInCollection:[OWSBackupManifestItem collection]]];
[obsoleteRecordNames addObjectsFromArray:[transaction allKeysInCollection:[OWSBackupFragment collection]]];
[obsoleteRecordNames minusSet:activeRecordNames];
[transaction removeObjectsForKeys:obsoleteRecordNames.allObjects
inCollection:[OWSBackupManifestItem collection]];
[transaction removeObjectsForKeys:obsoleteRecordNames.allObjects inCollection:[OWSBackupFragment collection]];
}];
}

View File

@ -26,8 +26,8 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
@property (nonatomic) OWSBackupIO *backupIO;
@property (nonatomic) NSArray<OWSBackupManifestItem *> *databaseItems;
@property (nonatomic) NSArray<OWSBackupManifestItem *> *attachmentsItems;
@property (nonatomic) NSArray<OWSBackupFragment *> *databaseItems;
@property (nonatomic) NSArray<OWSBackupFragment *> *attachmentsItems;
@end
@ -105,13 +105,13 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
OWSAssert(self.databaseItems);
OWSAssert(self.attachmentsItems);
NSMutableArray<OWSBackupManifestItem *> *allItems = [NSMutableArray new];
NSMutableArray<OWSBackupFragment *> *allItems = [NSMutableArray new];
[allItems addObjectsFromArray:self.databaseItems];
[allItems addObjectsFromArray:self.attachmentsItems];
// Record metadata for all items, so that we can re-use them in incremental backups after the restore.
[self.primaryStorage.newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (OWSBackupManifestItem *item in allItems) {
for (OWSBackupFragment *item in allItems) {
[item saveWithTransaction:transaction];
}
}];
@ -181,7 +181,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
return YES;
}
- (void)downloadFilesFromCloud:(NSMutableArray<OWSBackupManifestItem *> *)items
- (void)downloadFilesFromCloud:(NSMutableArray<OWSBackupFragment *> *)items
completion:(OWSBackupJobCompletion)completion
{
OWSAssert(items.count > 0);
@ -192,7 +192,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
[self downloadNextItemFromCloud:items recordCount:items.count completion:completion];
}
- (void)downloadNextItemFromCloud:(NSMutableArray<OWSBackupManifestItem *> *)items
- (void)downloadNextItemFromCloud:(NSMutableArray<OWSBackupFragment *> *)items
recordCount:(NSUInteger)recordCount
completion:(OWSBackupJobCompletion)completion
{
@ -208,7 +208,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
// All downloads are complete; exit.
return completion(nil);
}
OWSBackupManifestItem *item = items.lastObject;
OWSBackupFragment *item = items.lastObject;
[items removeLastObject];
CGFloat progress = (recordCount > 0 ? ((recordCount - items.count) / (CGFloat)recordCount) : 0.f);
@ -258,7 +258,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
NSString *attachmentsDirPath = [TSAttachmentStream attachmentsFolder];
NSUInteger count = 0;
for (OWSBackupManifestItem *item in self.attachmentsItems) {
for (OWSBackupFragment *item in self.attachmentsItems) {
if (self.isComplete) {
return;
}
@ -357,7 +357,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
}
NSUInteger count = 0;
for (OWSBackupManifestItem *item in self.databaseItems) {
for (OWSBackupFragment *item in self.databaseItems) {
if (self.isComplete) {
return;
}

View File

@ -3,7 +3,7 @@
//
#import "TSYapDatabaseObject.h"
#import <SignalServiceKit/OWSBackupManifestItem.h>
#import <SignalServiceKit/OWSBackupFragment.h>
NS_ASSUME_NONNULL_BEGIN
@ -25,8 +25,8 @@ typedef void (^OWSBackupJobManifestFailure)(NSError *error);
@interface OWSBackupManifestContents : NSObject
@property (nonatomic) NSArray<OWSBackupManifestItem *> *databaseItems;
@property (nonatomic) NSArray<OWSBackupManifestItem *> *attachmentsItems;
@property (nonatomic) NSArray<OWSBackupFragment *> *databaseItems;
@property (nonatomic) NSArray<OWSBackupFragment *> *attachmentsItems;
@end

View File

@ -216,12 +216,12 @@ NSString *const kOWSBackup_KeychainService = @"kOWSBackup_KeychainService";
DDLogVerbose(@"%@ json: %@", self.logTag, json);
NSArray<OWSBackupManifestItem *> *_Nullable databaseItems =
NSArray<OWSBackupFragment *> *_Nullable databaseItems =
[self parseItems:json key:kOWSBackup_ManifestKey_DatabaseFiles];
if (!databaseItems) {
return failure();
}
NSArray<OWSBackupManifestItem *> *_Nullable attachmentsItems =
NSArray<OWSBackupFragment *> *_Nullable attachmentsItems =
[self parseItems:json key:kOWSBackup_ManifestKey_AttachmentFiles];
if (!attachmentsItems) {
return failure();
@ -234,7 +234,7 @@ NSString *const kOWSBackup_KeychainService = @"kOWSBackup_KeychainService";
return success(contents);
}
- (nullable NSArray<OWSBackupManifestItem *> *)parseItems:(id)json key:(NSString *)key
- (nullable NSArray<OWSBackupFragment *> *)parseItems:(id)json key:(NSString *)key
{
OWSAssert(json);
OWSAssert(key.length);
@ -248,7 +248,7 @@ NSString *const kOWSBackup_KeychainService = @"kOWSBackup_KeychainService";
OWSProdLogAndFail(@"%@ manifest has invalid data: %@.", self.logTag, key);
return nil;
}
NSMutableArray<OWSBackupManifestItem *> *items = [NSMutableArray new];
NSMutableArray<OWSBackupFragment *> *items = [NSMutableArray new];
for (NSDictionary *itemMap in itemMaps) {
if (![itemMap isKindOfClass:[NSDictionary class]]) {
OWSProdLogAndFail(@"%@ manifest has invalid item: %@.", self.logTag, key);
@ -282,7 +282,7 @@ NSString *const kOWSBackup_KeychainService = @"kOWSBackup_KeychainService";
return nil;
}
OWSBackupManifestItem *item = [OWSBackupManifestItem new];
OWSBackupFragment *item = [OWSBackupFragment new];
item.recordName = recordName;
item.encryptionKey = encryptionKey;
item.relativeFilePath = relativeFilePath;

View File

@ -3,7 +3,7 @@
//
#import "DataSource.h"
#import "OWSBackupManifestItem.h"
#import "OWSBackupFragment.h"
#import "TSAttachment.h"
#if TARGET_OS_IPHONE
@ -35,9 +35,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) NSDate *creationTimestamp;
// Optional property. Only set for attachments which need "lazy backup restore."
@property (nonatomic, readonly, nullable) NSString *backupRestoreMetadataId;
#if TARGET_OS_IPHONE
- (nullable UIImage *)image;
- (nullable UIImage *)thumbnailImage;
@ -66,14 +63,15 @@ NS_ASSUME_NONNULL_BEGIN
+ (nullable NSError *)migrateToSharedData;
- (nullable OWSBackupManifestItem *)backupRestoreMetadata;
// Non-nil for attachments which need "lazy backup restore."
- (nullable OWSBackupFragment *)lazyRestoreFragment;
#pragma mark - Update With... Methods
// Marks attachment as needing "lazy backup restore."
- (void)updateWithBackupRestoreMetadata:(OWSBackupManifestItem *)backupRestoreMetadata;
- (void)updateWithLazyRestoreFragment:(OWSBackupFragment *)lazyRestoreFragment;
// Marks attachment as having completed "lazy backup restore."
- (void)updateWithBackupRestoreComplete;
- (void)updateWithLazyRestoreComplete;
@end

View File

@ -26,7 +26,8 @@ NS_ASSUME_NONNULL_BEGIN
// This property should only be accessed on the main thread.
@property (nullable, nonatomic) NSNumber *cachedAudioDurationSeconds;
@property (nonatomic, nullable) NSString *backupRestoreMetadataId;
// Optional property. Only set for attachments which need "lazy backup restore."
@property (nonatomic, nullable) NSString *lazyRestoreFragmentId;
@end
@ -612,40 +613,40 @@ NS_ASSUME_NONNULL_BEGIN
return audioDurationSeconds;
}
- (nullable OWSBackupManifestItem *)backupRestoreMetadata
- (nullable OWSBackupFragment *)lazyRestoreFragment
{
if (!self.backupRestoreMetadataId) {
if (!self.lazyRestoreFragmentId) {
return nil;
}
return [OWSBackupManifestItem fetchObjectWithUniqueID:self.backupRestoreMetadataId];
return [OWSBackupFragment fetchObjectWithUniqueID:self.lazyRestoreFragmentId];
}
#pragma mark - Update With... Methods
- (void)updateWithBackupRestoreMetadata:(OWSBackupManifestItem *)backupRestoreMetadata
- (void)updateWithLazyRestoreFragment:(OWSBackupFragment *)lazyRestoreFragment
{
OWSAssert(backupRestoreMetadata);
OWSAssert(lazyRestoreFragment);
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
if (!backupRestoreMetadata.uniqueId) {
if (!lazyRestoreFragment.uniqueId) {
// If metadata hasn't been saved yet, save now.
[backupRestoreMetadata saveWithTransaction:transaction];
[lazyRestoreFragment saveWithTransaction:transaction];
OWSAssert(backupRestoreMetadata.uniqueId);
OWSAssert(lazyRestoreFragment.uniqueId);
}
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(TSAttachmentStream *attachment) {
[attachment setBackupRestoreMetadataId:backupRestoreMetadata.uniqueId];
[attachment setLazyRestoreFragmentId:lazyRestoreFragment.uniqueId];
}];
}];
}
- (void)updateWithBackupRestoreComplete
- (void)updateWithLazyRestoreComplete
{
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[self applyChangeToSelfAndLatestCopy:transaction
changeBlock:^(TSAttachmentStream *attachment) {
[attachment setBackupRestoreMetadataId:nil];
[attachment setLazyRestoreFragmentId:nil];
}];
}];
}

View File

@ -354,7 +354,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
return nil;
}
TSAttachmentStream *attachmentStream = (TSAttachmentStream *)object;
if (attachmentStream.backupRestoreMetadata) {
if (attachmentStream.lazyRestoreFragment) {
return TSLazyRestoreAttachmentsGroup;
} else {
return nil;

View File

@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
// * Backup exports can reuse fragments from previous Backup exports even if they
// don't complete (i.e. backup export resume).
// * Backup exports can reuse fragments from the backup import, if any.
@interface OWSBackupManifestItem : TSYapDatabaseObject
@interface OWSBackupFragment : TSYapDatabaseObject
@property (nonatomic) NSString *recordName;

View File

@ -2,11 +2,11 @@
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSBackupManifestItem.h"
#import "OWSBackupFragment.h"
NS_ASSUME_NONNULL_BEGIN
@implementation OWSBackupManifestItem
@implementation OWSBackupFragment
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
{