diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.h b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.h index 530997f53..212d3051b 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.h +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.h @@ -1,12 +1,16 @@ -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "OWSOutgoingSyncMessage.h" NS_ASSUME_NONNULL_BEGIN +@class YapDatabaseReadTransaction; + @interface OWSSyncGroupsMessage : OWSOutgoingSyncMessage -- (NSData *)buildPlainTextAttachmentData; +- (NSData *)buildPlainTextAttachmentDataWithTransaction:(YapDatabaseReadTransaction *)transaction; @end diff --git a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m index 575f3d9eb..651a7edb7 100644 --- a/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m +++ b/SignalServiceKit/src/Messages/DeviceSyncing/OWSSyncGroupsMessage.m @@ -40,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN return syncMessageBuilder; } -- (NSData *)buildPlainTextAttachmentData +- (NSData *)buildPlainTextAttachmentDataWithTransaction:(YapDatabaseReadTransaction *)transaction { // TODO use temp file stream to avoid loading everything into memory at once // First though, we need to re-engineer our attachment process to accept streams (encrypting with stream, @@ -49,14 +49,16 @@ NS_ASSUME_NONNULL_BEGIN [dataOutputStream open]; OWSGroupsOutputStream *groupsOutputStream = [OWSGroupsOutputStream streamWithOutputStream:dataOutputStream]; - [TSGroupThread enumerateCollectionObjectsUsingBlock:^(id obj, BOOL *stop) { - if (![obj isKindOfClass:[TSGroupThread class]]) { - DDLogVerbose(@"Ignoring non group thread in thread collection: %@", obj); - return; - } - TSGroupModel *group = ((TSGroupThread *)obj).groupModel; - [groupsOutputStream writeGroup:group]; - }]; + [TSGroupThread + enumerateCollectionObjectsWithTransaction:transaction + usingBlock:^(id obj, BOOL *stop) { + if (![obj isKindOfClass:[TSGroupThread class]]) { + DDLogVerbose(@"Ignoring non group thread in thread collection: %@", obj); + return; + } + TSGroupModel *group = ((TSGroupThread *)obj).groupModel; + [groupsOutputStream writeGroup:group]; + }]; [groupsOutputStream flush]; [dataOutputStream close]; diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 4b146b86b..5eb9e024b 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -615,8 +615,8 @@ NS_ASSUME_NONNULL_BEGIN }]; } else if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeGroups) { OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] init]; - DataSource *dataSource = - [DataSourceValue dataSourceWithSyncMessage:[syncGroupsMessage buildPlainTextAttachmentData]]; + DataSource *dataSource = [DataSourceValue + dataSourceWithSyncMessage:[syncGroupsMessage buildPlainTextAttachmentDataWithTransaction:transaction]]; [self.messageSender sendTemporaryAttachmentData:dataSource contentType:OWSMimeTypeApplicationOctetStream inMessage:syncGroupsMessage diff --git a/SignalServiceKit/src/Network/API/OWSUploadingService.m b/SignalServiceKit/src/Network/API/OWSUploadingService.m index 97127bdb2..3cc067802 100644 --- a/SignalServiceKit/src/Network/API/OWSUploadingService.m +++ b/SignalServiceKit/src/Network/API/OWSUploadingService.m @@ -107,9 +107,7 @@ static const CGFloat kAttachmentUploadProgressTheta = 0.001f; DDLogInfo(@"%@ Uploaded attachment: %p.", self.tag, attachmentStream); attachmentStream.serverId = serverId; attachmentStream.isUploaded = YES; - [attachmentStream save]; - - successHandlerWrapper(); + [attachmentStream saveAsyncWithCompletionBlock:successHandlerWrapper]; } failure:failureHandlerWrapper]; diff --git a/SignalServiceKit/src/Storage/TSYapDatabaseObject.h b/SignalServiceKit/src/Storage/TSYapDatabaseObject.h index 07dbcc6f8..cb68f9496 100644 --- a/SignalServiceKit/src/Storage/TSYapDatabaseObject.h +++ b/SignalServiceKit/src/Storage/TSYapDatabaseObject.h @@ -81,10 +81,22 @@ + (instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID NS_SWIFT_NAME(fetch(uniqueId:)); /** - * Saves the object with a new YapDatabaseConnection + * Saves the object with the shared readWrite connection. + * + * This method will block if another readWrite transaction is open. */ - (void)save; +/** + * Saves the object with the shared readWrite connection - does not block. + * + * Be mindful that this method may clobber other changes persisted + * while waiting to open the readWrite transaction. + * + * @param completionBlock is called on the main thread + */ +- (void)saveAsyncWithCompletionBlock:(void (^_Nullable)(void))completionBlock; + /** * Saves the object with the provided transaction * diff --git a/SignalServiceKit/src/Storage/TSYapDatabaseObject.m b/SignalServiceKit/src/Storage/TSYapDatabaseObject.m index 032d55b48..ec392ccde 100644 --- a/SignalServiceKit/src/Storage/TSYapDatabaseObject.m +++ b/SignalServiceKit/src/Storage/TSYapDatabaseObject.m @@ -37,6 +37,14 @@ }]; } +- (void)saveAsyncWithCompletionBlock:(void (^_Nullable)(void))completionBlock +{ + [[self dbReadWriteConnection] asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { + [self saveWithTransaction:transaction]; + } + completionBlock:completionBlock]; +} + - (void)touchWithTransaction:(YapDatabaseReadWriteTransaction *)transaction { [transaction touchObjectForKey:self.uniqueId inCollection:[self.class collection]];