From 3f36f5467de4c191fa2903743e5a210420e9d49a Mon Sep 17 00:00:00 2001 From: Greg Soltis Date: Fri, 30 Mar 2018 10:18:25 -0700 Subject: Drop FSTWriteGroup (#986) * Drop write group from remote document change buffer * Unwind some group dependendencies in local store * Write group dropped from local store * Drop write group from mutation queue tests * Drop write group usage from query cache tests * Drop write groups from remote document cache tests * Drop write groups from remote document change buffer tests * Drop write groups and the write group tracker * Style * Put the action in transaction * Merge master, fix test * Fix some compiler warnings but mostly trigger travis * Responses to feedback --- Firestore/Source/Local/FSTLevelDB.mm | 23 +- Firestore/Source/Local/FSTLocalStore.mm | 472 ++++++++++----------- Firestore/Source/Local/FSTMemoryPersistence.mm | 14 - Firestore/Source/Local/FSTPersistence.h | 26 +- .../Source/Local/FSTRemoteDocumentChangeBuffer.h | 6 +- .../Source/Local/FSTRemoteDocumentChangeBuffer.mm | 2 +- Firestore/Source/Local/FSTWriteGroup.h | 89 ---- Firestore/Source/Local/FSTWriteGroup.mm | 96 ----- Firestore/Source/Local/FSTWriteGroupTracker.h | 50 --- Firestore/Source/Local/FSTWriteGroupTracker.mm | 63 --- 10 files changed, 237 insertions(+), 604 deletions(-) delete mode 100644 Firestore/Source/Local/FSTWriteGroup.h delete mode 100644 Firestore/Source/Local/FSTWriteGroup.mm delete mode 100644 Firestore/Source/Local/FSTWriteGroupTracker.h delete mode 100644 Firestore/Source/Local/FSTWriteGroupTracker.mm (limited to 'Firestore/Source/Local') diff --git a/Firestore/Source/Local/FSTLevelDB.mm b/Firestore/Source/Local/FSTLevelDB.mm index 922c5b4..4812228 100644 --- a/Firestore/Source/Local/FSTLevelDB.mm +++ b/Firestore/Source/Local/FSTLevelDB.mm @@ -23,8 +23,6 @@ #import "Firestore/Source/Local/FSTLevelDBMutationQueue.h" #import "Firestore/Source/Local/FSTLevelDBQueryCache.h" #import "Firestore/Source/Local/FSTLevelDBRemoteDocumentCache.h" -#import "Firestore/Source/Local/FSTWriteGroup.h" -#import "Firestore/Source/Local/FSTWriteGroupTracker.h" #import "Firestore/Source/Remote/FSTSerializerBeta.h" #import "Firestore/Source/Util/FSTAssert.h" #import "Firestore/Source/Util/FSTLogger.h" @@ -55,7 +53,6 @@ using leveldb::WriteOptions; @interface FSTLevelDB () @property(nonatomic, copy) NSString *directory; -@property(nonatomic, strong) FSTWriteGroupTracker *writeGroupTracker; @property(nonatomic, assign, getter=isStarted) BOOL started; @property(nonatomic, strong, readonly) FSTLocalSerializer *serializer; @@ -79,7 +76,6 @@ using leveldb::WriteOptions; serializer:(FSTLocalSerializer *)serializer { if (self = [super init]) { _directory = [directory copy]; - _writeGroupTracker = [FSTWriteGroupTracker tracker]; _serializer = serializer; _transactionRunner.SetBackingPersistence(self); } @@ -148,7 +144,7 @@ using leveldb::WriteOptions; return NO; } _ptr.reset(database); - LevelDbTransaction transaction(_ptr.get()); + LevelDbTransaction transaction(_ptr.get(), "Start LevelDB"); [FSTLevelDBMigrations runMigrationsWithTransaction:&transaction]; transaction.Commit(); return YES; @@ -229,9 +225,9 @@ using leveldb::WriteOptions; return [[FSTLevelDBRemoteDocumentCache alloc] initWithDB:self serializer:self.serializer]; } -- (void)startTransaction { +- (void)startTransaction:(absl::string_view)label { FSTAssert(_transaction == nullptr, @"Starting a transaction while one is already outstanding"); - _transaction = absl::make_unique(_ptr.get()); + _transaction = absl::make_unique(_ptr.get(), label); } - (void)commitTransaction { @@ -240,19 +236,6 @@ using leveldb::WriteOptions; _transaction.reset(); } -- (FSTWriteGroup *)startGroupWithAction:(NSString *)action { - FSTAssert(_transaction == nullptr, @"Starting a transaction while one is already outstanding"); - _transaction = absl::make_unique(_ptr.get()); - return [self.writeGroupTracker startGroupWithAction:action transaction:_transaction.get()]; -} - -- (void)commitGroup:(FSTWriteGroup *)group { - FSTAssert(_transaction != nullptr, @"Committing a transaction before one is started"); - [self.writeGroupTracker endGroup:group]; - _transaction->Commit(); - _transaction.reset(); -} - - (void)shutdown { FSTAssert(self.isStarted, @"FSTLevelDB shutdown without start!"); self.started = NO; diff --git a/Firestore/Source/Local/FSTLocalStore.mm b/Firestore/Source/Local/FSTLocalStore.mm index 74eab48..412ade2 100644 --- a/Firestore/Source/Local/FSTLocalStore.mm +++ b/Firestore/Source/Local/FSTLocalStore.mm @@ -31,7 +31,6 @@ #import "Firestore/Source/Local/FSTReferenceSet.h" #import "Firestore/Source/Local/FSTRemoteDocumentCache.h" #import "Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.h" -#import "Firestore/Source/Local/FSTWriteGroup.h" #import "Firestore/Source/Model/FSTDocument.h" #import "Firestore/Source/Model/FSTDocumentDictionary.h" #import "Firestore/Source/Model/FSTMutation.h" @@ -132,27 +131,27 @@ NS_ASSUME_NONNULL_BEGIN } - (void)startMutationQueue { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Start MutationQueue"]; - [self.mutationQueue start]; - - // If we have any leftover mutation batch results from a prior run, just drop them. - // TODO(http://b/33446471): We probably need to repopulate heldBatchResults or similar instead, - // but that is not straightforward since we're not persisting the write ack versions. - [self.heldBatchResults removeAllObjects]; - - // TODO(mikelehen): This is the only usage of getAllMutationBatchesThroughBatchId:. Consider - // removing it in favor of a getAcknowledgedBatches method. - FSTBatchID highestAck = [self.mutationQueue highestAcknowledgedBatchID]; - if (highestAck != kFSTBatchIDUnknown) { - NSArray *batches = - [self.mutationQueue allMutationBatchesThroughBatchID:highestAck]; - if (batches.count > 0) { - // NOTE: This could be more efficient if we had a removeBatchesThroughBatchID, but this set - // should be very small and this code should go away eventually. - [self.mutationQueue removeMutationBatches:batches]; + self.persistence.run("Start MutationQueue", [&]() { + [self.mutationQueue start]; + + // If we have any leftover mutation batch results from a prior run, just drop them. + // TODO(http://b/33446471): We probably need to repopulate heldBatchResults or similar instead, + // but that is not straightforward since we're not persisting the write ack versions. + [self.heldBatchResults removeAllObjects]; + + // TODO(mikelehen): This is the only usage of getAllMutationBatchesThroughBatchId:. Consider + // removing it in favor of a getAcknowledgedBatches method. + FSTBatchID highestAck = [self.mutationQueue highestAcknowledgedBatchID]; + if (highestAck != kFSTBatchIDUnknown) { + NSArray *batches = + [self.mutationQueue allMutationBatchesThroughBatchID:highestAck]; + if (batches.count > 0) { + // NOTE: This could be more efficient if we had a removeBatchesThroughBatchID, but this set + // should be very small and this code should go away eventually. + [self.mutationQueue removeMutationBatches:batches]; + } } - } - [self.persistence commitGroup:group]; + }); } - (void)startQueryCache { @@ -166,9 +165,9 @@ NS_ASSUME_NONNULL_BEGIN - (FSTMaybeDocumentDictionary *)userDidChange:(const User &)user { // Swap out the mutation queue, grabbing the pending mutation batches before and after. - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"OldBatches"]; - NSArray *oldBatches = [self.mutationQueue allMutationBatches]; - [self.persistence commitGroup:group]; + NSArray *oldBatches = self.persistence.run( + "OldBatches", + [&]() -> NSArray * { return [self.mutationQueue allMutationBatches]; }); [self.garbageCollector removeGarbageSource:self.mutationQueue]; @@ -177,83 +176,79 @@ NS_ASSUME_NONNULL_BEGIN [self startMutationQueue]; - group = [self.persistence startGroupWithAction:@"NewBatches"]; - NSArray *newBatches = [self.mutationQueue allMutationBatches]; - - // Recreate our LocalDocumentsView using the new MutationQueue. - self.localDocuments = [FSTLocalDocumentsView viewWithRemoteDocumentCache:self.remoteDocumentCache - mutationQueue:self.mutationQueue]; - - // Union the old/new changed keys. - FSTDocumentKeySet *changedKeys = [FSTDocumentKeySet keySet]; - for (NSArray *batches in @[ oldBatches, newBatches ]) { - for (FSTMutationBatch *batch in batches) { - for (FSTMutation *mutation in batch.mutations) { - changedKeys = [changedKeys setByAddingObject:mutation.key]; + return self.persistence.run("NewBatches", [&]() -> FSTMaybeDocumentDictionary * { + NSArray *newBatches = [self.mutationQueue allMutationBatches]; + + // Recreate our LocalDocumentsView using the new MutationQueue. + self.localDocuments = + [FSTLocalDocumentsView viewWithRemoteDocumentCache:self.remoteDocumentCache + mutationQueue:self.mutationQueue]; + + // Union the old/new changed keys. + FSTDocumentKeySet *changedKeys = [FSTDocumentKeySet keySet]; + for (NSArray *batches in @[ oldBatches, newBatches ]) { + for (FSTMutationBatch *batch in batches) { + for (FSTMutation *mutation in batch.mutations) { + changedKeys = [changedKeys setByAddingObject:mutation.key]; + } } } - } - // Return the set of all (potentially) changed documents as the result of the user change. - FSTMaybeDocumentDictionary *result = [self.localDocuments documentsForKeys:changedKeys]; - [self.persistence commitGroup:group]; - return result; + // Return the set of all (potentially) changed documents as the result of the user change. + return [self.localDocuments documentsForKeys:changedKeys]; + }); } - (FSTLocalWriteResult *)locallyWriteMutations:(NSArray *)mutations { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Locally write mutations"]; - FIRTimestamp *localWriteTime = [FIRTimestamp timestamp]; - FSTMutationBatch *batch = - [self.mutationQueue addMutationBatchWithWriteTime:localWriteTime mutations:mutations]; - FSTDocumentKeySet *keys = [batch keys]; - FSTMaybeDocumentDictionary *changedDocuments = [self.localDocuments documentsForKeys:keys]; - [self.persistence commitGroup:group]; - return [FSTLocalWriteResult resultForBatchID:batch.batchID changes:changedDocuments]; + return self.persistence.run("Locally write mutations", [&]() -> FSTLocalWriteResult * { + FIRTimestamp *localWriteTime = [FIRTimestamp timestamp]; + FSTMutationBatch *batch = + [self.mutationQueue addMutationBatchWithWriteTime:localWriteTime mutations:mutations]; + FSTDocumentKeySet *keys = [batch keys]; + FSTMaybeDocumentDictionary *changedDocuments = [self.localDocuments documentsForKeys:keys]; + return [FSTLocalWriteResult resultForBatchID:batch.batchID changes:changedDocuments]; + }); } - (FSTMaybeDocumentDictionary *)acknowledgeBatchWithResult:(FSTMutationBatchResult *)batchResult { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Acknowledge batch"]; - id mutationQueue = self.mutationQueue; + return self.persistence.run("Acknowledge batch", [&]() -> FSTMaybeDocumentDictionary * { + id mutationQueue = self.mutationQueue; - [mutationQueue acknowledgeBatch:batchResult.batch streamToken:batchResult.streamToken]; + [mutationQueue acknowledgeBatch:batchResult.batch streamToken:batchResult.streamToken]; - FSTDocumentKeySet *affected; - if ([self shouldHoldBatchResultWithVersion:batchResult.commitVersion]) { - [self.heldBatchResults addObject:batchResult]; - affected = [FSTDocumentKeySet keySet]; - } else { - FSTRemoteDocumentChangeBuffer *remoteDocuments = - [FSTRemoteDocumentChangeBuffer changeBufferWithCache:self.remoteDocumentCache]; + FSTDocumentKeySet *affected; + if ([self shouldHoldBatchResultWithVersion:batchResult.commitVersion]) { + [self.heldBatchResults addObject:batchResult]; + affected = [FSTDocumentKeySet keySet]; + } else { + FSTRemoteDocumentChangeBuffer *remoteDocuments = + [FSTRemoteDocumentChangeBuffer changeBufferWithCache:self.remoteDocumentCache]; - affected = - [self releaseBatchResults:@[ batchResult ] group:group remoteDocuments:remoteDocuments]; + affected = [self releaseBatchResults:@[ batchResult ] remoteDocuments:remoteDocuments]; - [remoteDocuments applyToWriteGroup:group]; - } + [remoteDocuments apply]; + } - [self.mutationQueue performConsistencyCheck]; + [self.mutationQueue performConsistencyCheck]; - FSTMaybeDocumentDictionary *result = [self.localDocuments documentsForKeys:affected]; - [self.persistence commitGroup:group]; - return result; + return [self.localDocuments documentsForKeys:affected]; + }); } - (FSTMaybeDocumentDictionary *)rejectBatchID:(FSTBatchID)batchID { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Reject batch"]; - - FSTMutationBatch *toReject = [self.mutationQueue lookupMutationBatch:batchID]; - FSTAssert(toReject, @"Attempt to reject nonexistent batch!"); + return self.persistence.run("Reject batch", [&]() -> FSTMaybeDocumentDictionary * { + FSTMutationBatch *toReject = [self.mutationQueue lookupMutationBatch:batchID]; + FSTAssert(toReject, @"Attempt to reject nonexistent batch!"); - FSTBatchID lastAcked = [self.mutationQueue highestAcknowledgedBatchID]; - FSTAssert(batchID > lastAcked, @"Acknowledged batches can't be rejected."); + FSTBatchID lastAcked = [self.mutationQueue highestAcknowledgedBatchID]; + FSTAssert(batchID > lastAcked, @"Acknowledged batches can't be rejected."); - FSTDocumentKeySet *affected = [self removeMutationBatch:toReject group:group]; + FSTDocumentKeySet *affected = [self removeMutationBatch:toReject]; - [self.mutationQueue performConsistencyCheck]; + [self.mutationQueue performConsistencyCheck]; - FSTMaybeDocumentDictionary *result = [self.localDocuments documentsForKeys:affected]; - [self.persistence commitGroup:group]; - return result; + return [self.localDocuments documentsForKeys:affected]; + }); } - (nullable NSData *)lastStreamToken { @@ -261,10 +256,8 @@ NS_ASSUME_NONNULL_BEGIN } - (void)setLastStreamToken:(nullable NSData *)streamToken { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Set stream token"]; - - [self.mutationQueue setLastStreamToken:streamToken]; - [self.persistence commitGroup:group]; + self.persistence.run("Set stream token", + [&]() { [self.mutationQueue setLastStreamToken:streamToken]; }); } - (FSTSnapshotVersion *)lastRemoteSnapshotVersion { @@ -272,207 +265,197 @@ NS_ASSUME_NONNULL_BEGIN } - (FSTMaybeDocumentDictionary *)applyRemoteEvent:(FSTRemoteEvent *)remoteEvent { - id queryCache = self.queryCache; - - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Apply remote event"]; - FSTRemoteDocumentChangeBuffer *remoteDocuments = - [FSTRemoteDocumentChangeBuffer changeBufferWithCache:self.remoteDocumentCache]; + return self.persistence.run("Apply remote event", [&]() -> FSTMaybeDocumentDictionary * { + id queryCache = self.queryCache; - [remoteEvent.targetChanges enumerateKeysAndObjectsUsingBlock:^( - NSNumber *targetIDNumber, FSTTargetChange *change, BOOL *stop) { - FSTTargetID targetID = targetIDNumber.intValue; + FSTRemoteDocumentChangeBuffer *remoteDocuments = + [FSTRemoteDocumentChangeBuffer changeBufferWithCache:self.remoteDocumentCache]; - // Do not ref/unref unassigned targetIDs - it may lead to leaks. - FSTQueryData *queryData = self.targetIDs[targetIDNumber]; - if (!queryData) { - return; - } + [remoteEvent.targetChanges enumerateKeysAndObjectsUsingBlock:^( + NSNumber *targetIDNumber, FSTTargetChange *change, BOOL *stop) { + FSTTargetID targetID = targetIDNumber.intValue; - FSTTargetMapping *mapping = change.mapping; - if (mapping) { - // First make sure that all references are deleted. - if ([mapping isKindOfClass:[FSTResetMapping class]]) { - FSTResetMapping *reset = (FSTResetMapping *)mapping; - [queryCache removeMatchingKeysForTargetID:targetID]; - [queryCache addMatchingKeys:reset.documents forTargetID:targetID]; + // Do not ref/unref unassigned targetIDs - it may lead to leaks. + FSTQueryData *queryData = self.targetIDs[targetIDNumber]; + if (!queryData) { + return; + } - } else if ([mapping isKindOfClass:[FSTUpdateMapping class]]) { - FSTUpdateMapping *update = (FSTUpdateMapping *)mapping; - [queryCache removeMatchingKeys:update.removedDocuments forTargetID:targetID]; - [queryCache addMatchingKeys:update.addedDocuments forTargetID:targetID]; + FSTTargetMapping *mapping = change.mapping; + if (mapping) { + // First make sure that all references are deleted. + if ([mapping isKindOfClass:[FSTResetMapping class]]) { + FSTResetMapping *reset = (FSTResetMapping *)mapping; + [queryCache removeMatchingKeysForTargetID:targetID]; + [queryCache addMatchingKeys:reset.documents forTargetID:targetID]; + + } else if ([mapping isKindOfClass:[FSTUpdateMapping class]]) { + FSTUpdateMapping *update = (FSTUpdateMapping *)mapping; + [queryCache removeMatchingKeys:update.removedDocuments forTargetID:targetID]; + [queryCache addMatchingKeys:update.addedDocuments forTargetID:targetID]; + + } else { + FSTFail(@"Unknown mapping type: %@", mapping); + } + } + // Update the resume token if the change includes one. Don't clear any preexisting value. + NSData *resumeToken = change.resumeToken; + if (resumeToken.length > 0) { + queryData = [queryData queryDataByReplacingSnapshotVersion:change.snapshotVersion + resumeToken:resumeToken]; + self.targetIDs[targetIDNumber] = queryData; + [self.queryCache updateQueryData:queryData]; + } + }]; + + // TODO(klimt): This could probably be an NSMutableDictionary. + FSTDocumentKeySet *changedDocKeys = [FSTDocumentKeySet keySet]; + for (const auto &kv : remoteEvent.documentUpdates) { + const DocumentKey &key = kv.first; + FSTMaybeDocument *doc = kv.second; + changedDocKeys = [changedDocKeys setByAddingObject:key]; + FSTMaybeDocument *existingDoc = [remoteDocuments entryForKey:key]; + // Make sure we don't apply an old document version to the remote cache, though we + // make an exception for [SnapshotVersion noVersion] which can happen for manufactured + // events (e.g. in the case of a limbo document resolution failing). + if (!existingDoc || [doc.version isEqual:[FSTSnapshotVersion noVersion]] || + [doc.version compare:existingDoc.version] != NSOrderedAscending) { + [remoteDocuments addEntry:doc]; } else { - FSTFail(@"Unknown mapping type: %@", mapping); + FSTLog( + @"FSTLocalStore Ignoring outdated watch update for %s. " + "Current version: %@ Watch version: %@", + key.ToString().c_str(), existingDoc.version, doc.version); } - } - // Update the resume token if the change includes one. Don't clear any preexisting value. - NSData *resumeToken = change.resumeToken; - if (resumeToken.length > 0) { - queryData = [queryData queryDataByReplacingSnapshotVersion:change.snapshotVersion - resumeToken:resumeToken]; - self.targetIDs[targetIDNumber] = queryData; - [self.queryCache updateQueryData:queryData]; + // The document might be garbage because it was unreferenced by everything. + // Make sure to mark it as garbage if it is... + [self.garbageCollector addPotentialGarbageKey:key]; } - }]; - // TODO(klimt): This could probably be an NSMutableDictionary. - FSTDocumentKeySet *changedDocKeys = [FSTDocumentKeySet keySet]; - for (const auto &kv : remoteEvent.documentUpdates) { - const DocumentKey &key = kv.first; - FSTMaybeDocument *doc = kv.second; - changedDocKeys = [changedDocKeys setByAddingObject:key]; - FSTMaybeDocument *existingDoc = [remoteDocuments entryForKey:key]; - // Make sure we don't apply an old document version to the remote cache, though we - // make an exception for [SnapshotVersion noVersion] which can happen for manufactured - // events (e.g. in the case of a limbo document resolution failing). - if (!existingDoc || [doc.version isEqual:[FSTSnapshotVersion noVersion]] || - [doc.version compare:existingDoc.version] != NSOrderedAscending) { - [remoteDocuments addEntry:doc]; - } else { - FSTLog( - @"FSTLocalStore Ignoring outdated watch update for %s. " - "Current version: %@ Watch version: %@", - key.ToString().c_str(), existingDoc.version, doc.version); + // HACK: The only reason we allow omitting snapshot version is so we can synthesize remote + // events when we get permission denied errors while trying to resolve the state of a locally + // cached document that is in limbo. + FSTSnapshotVersion *lastRemoteVersion = [self.queryCache lastRemoteSnapshotVersion]; + FSTSnapshotVersion *remoteVersion = remoteEvent.snapshotVersion; + if (![remoteVersion isEqual:[FSTSnapshotVersion noVersion]]) { + FSTAssert([remoteVersion compare:lastRemoteVersion] != NSOrderedAscending, + @"Watch stream reverted to previous snapshot?? (%@ < %@)", remoteVersion, + lastRemoteVersion); + [self.queryCache setLastRemoteSnapshotVersion:remoteVersion]; } - // The document might be garbage because it was unreferenced by everything. - // Make sure to mark it as garbage if it is... - [self.garbageCollector addPotentialGarbageKey:key]; - } - - // HACK: The only reason we allow omitting snapshot version is so we can synthesize remote events - // when we get permission denied errors while trying to resolve the state of a locally cached - // document that is in limbo. - FSTSnapshotVersion *lastRemoteVersion = [self.queryCache lastRemoteSnapshotVersion]; - FSTSnapshotVersion *remoteVersion = remoteEvent.snapshotVersion; - if (![remoteVersion isEqual:[FSTSnapshotVersion noVersion]]) { - FSTAssert([remoteVersion compare:lastRemoteVersion] != NSOrderedAscending, - @"Watch stream reverted to previous snapshot?? (%@ < %@)", remoteVersion, - lastRemoteVersion); - [self.queryCache setLastRemoteSnapshotVersion:remoteVersion]; - } - - FSTDocumentKeySet *releasedWriteKeys = - [self releaseHeldBatchResultsWithGroup:group remoteDocuments:remoteDocuments]; + FSTDocumentKeySet *releasedWriteKeys = + [self releaseHeldBatchResultsWithRemoteDocuments:remoteDocuments]; - [remoteDocuments applyToWriteGroup:group]; + [remoteDocuments apply]; - // Union the two key sets. - __block FSTDocumentKeySet *keysToRecalc = changedDocKeys; - [releasedWriteKeys enumerateObjectsUsingBlock:^(FSTDocumentKey *key, BOOL *stop) { - keysToRecalc = [keysToRecalc setByAddingObject:key]; - }]; + // Union the two key sets. + __block FSTDocumentKeySet *keysToRecalc = changedDocKeys; + [releasedWriteKeys enumerateObjectsUsingBlock:^(FSTDocumentKey *key, BOOL *stop) { + keysToRecalc = [keysToRecalc setByAddingObject:key]; + }]; - FSTMaybeDocumentDictionary *result = [self.localDocuments documentsForKeys:keysToRecalc]; - [self.persistence commitGroup:group]; - return result; + return [self.localDocuments documentsForKeys:keysToRecalc]; + }); } - (void)notifyLocalViewChanges:(NSArray *)viewChanges { - FSTReferenceSet *localViewReferences = self.localViewReferences; - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"NotifyLocalViewChanges"]; - for (FSTLocalViewChanges *view in viewChanges) { - FSTQueryData *queryData = [self.queryCache queryDataForQuery:view.query]; - FSTAssert(queryData, @"Local view changes contain unallocated query."); - FSTTargetID targetID = queryData.targetID; - [localViewReferences addReferencesToKeys:view.addedKeys forID:targetID]; - [localViewReferences removeReferencesToKeys:view.removedKeys forID:targetID]; - } - [self.persistence commitGroup:group]; + self.persistence.run("NotifyLocalViewChanges", [&]() { + FSTReferenceSet *localViewReferences = self.localViewReferences; + for (FSTLocalViewChanges *view in viewChanges) { + FSTQueryData *queryData = [self.queryCache queryDataForQuery:view.query]; + FSTAssert(queryData, @"Local view changes contain unallocated query."); + FSTTargetID targetID = queryData.targetID; + [localViewReferences addReferencesToKeys:view.addedKeys forID:targetID]; + [localViewReferences removeReferencesToKeys:view.removedKeys forID:targetID]; + } + }); } - (nullable FSTMutationBatch *)nextMutationBatchAfterBatchID:(FSTBatchID)batchID { - FSTMutationBatch *result = self.persistence.run([&]() -> FSTMutationBatch * { - return [self.mutationQueue nextMutationBatchAfterBatchID:batchID]; - }); + FSTMutationBatch *result = + self.persistence.run("NextMutationBatchAfterBatchID", [&]() -> FSTMutationBatch * { + return [self.mutationQueue nextMutationBatchAfterBatchID:batchID]; + }); return result; } - (nullable FSTMaybeDocument *)readDocument:(const DocumentKey &)key { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"ReadDocument"]; - FSTMaybeDocument *result = [self.localDocuments documentForKey:key]; - [self.persistence commitGroup:group]; - return result; + return self.persistence.run("ReadDocument", [&]() -> FSTMaybeDocument *_Nullable { + return [self.localDocuments documentForKey:key]; + }); } - (FSTQueryData *)allocateQuery:(FSTQuery *)query { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Allocate query"]; - FSTQueryData *cached = [self.queryCache queryDataForQuery:query]; - FSTTargetID targetID; - FSTListenSequenceNumber sequenceNumber = [self.listenSequence next]; - if (cached) { - // This query has been listened to previously, so reuse the previous targetID. - // TODO(mcg): freshen last accessed date? - targetID = cached.targetID; - } else { - targetID = _targetIDGenerator.NextId(); - cached = [[FSTQueryData alloc] initWithQuery:query - targetID:targetID - listenSequenceNumber:sequenceNumber - purpose:FSTQueryPurposeListen]; - [self.queryCache addQueryData:cached]; - } - [self.persistence commitGroup:group]; + FSTQueryData *queryData = self.persistence.run("Allocate query", [&]() -> FSTQueryData * { + FSTQueryData *cached = [self.queryCache queryDataForQuery:query]; + // TODO(mcg): freshen last accessed date if cached exists? + if (!cached) { + cached = [[FSTQueryData alloc] initWithQuery:query + targetID:_targetIDGenerator.NextId() + listenSequenceNumber:[self.listenSequence next] + purpose:FSTQueryPurposeListen]; + [self.queryCache addQueryData:cached]; + } + return cached; + }); // Sanity check to ensure that even when resuming a query it's not currently active. - FSTBoxedTargetID *boxedTargetID = @(targetID); + FSTBoxedTargetID *boxedTargetID = @(queryData.targetID); FSTAssert(!self.targetIDs[boxedTargetID], @"Tried to allocate an already allocated query: %@", query); - self.targetIDs[boxedTargetID] = cached; - return cached; + self.targetIDs[boxedTargetID] = queryData; + return queryData; } - (void)releaseQuery:(FSTQuery *)query { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Release query"]; - - FSTQueryData *queryData = [self.queryCache queryDataForQuery:query]; - FSTAssert(queryData, @"Tried to release nonexistent query: %@", query); - - [self.localViewReferences removeReferencesForID:queryData.targetID]; - if (self.garbageCollector.isEager) { - [self.queryCache removeQueryData:queryData]; - } - [self.targetIDs removeObjectForKey:@(queryData.targetID)]; + self.persistence.run("Release query", [&]() { + FSTQueryData *queryData = [self.queryCache queryDataForQuery:query]; + FSTAssert(queryData, @"Tried to release nonexistent query: %@", query); - // If this was the last watch target, then we won't get any more watch snapshots, so we should - // release any held batch results. - if ([self.targetIDs count] == 0) { - FSTRemoteDocumentChangeBuffer *remoteDocuments = - [FSTRemoteDocumentChangeBuffer changeBufferWithCache:self.remoteDocumentCache]; + [self.localViewReferences removeReferencesForID:queryData.targetID]; + if (self.garbageCollector.isEager) { + [self.queryCache removeQueryData:queryData]; + } + [self.targetIDs removeObjectForKey:@(queryData.targetID)]; - [self releaseHeldBatchResultsWithGroup:group remoteDocuments:remoteDocuments]; + // If this was the last watch target, then we won't get any more watch snapshots, so we should + // release any held batch results. + if ([self.targetIDs count] == 0) { + FSTRemoteDocumentChangeBuffer *remoteDocuments = + [FSTRemoteDocumentChangeBuffer changeBufferWithCache:self.remoteDocumentCache]; - [remoteDocuments applyToWriteGroup:group]; - } + [self releaseHeldBatchResultsWithRemoteDocuments:remoteDocuments]; - [self.persistence commitGroup:group]; + [remoteDocuments apply]; + } + }); } - (FSTDocumentDictionary *)executeQuery:(FSTQuery *)query { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"ExecuteQuery"]; - FSTDocumentDictionary *result = [self.localDocuments documentsMatchingQuery:query]; - [self.persistence commitGroup:group]; - return result; + return self.persistence.run("ExecuteQuery", [&]() -> FSTDocumentDictionary * { + return [self.localDocuments documentsMatchingQuery:query]; + }); } - (FSTDocumentKeySet *)remoteDocumentKeysForTarget:(FSTTargetID)targetID { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"RemoteDocumentKeysForTarget"]; - FSTDocumentKeySet *keySet = [self.queryCache matchingKeysForTargetID:targetID]; - [self.persistence commitGroup:group]; - return keySet; + return self.persistence.run("RemoteDocumentKeysForTarget", [&]() -> FSTDocumentKeySet * { + return [self.queryCache matchingKeysForTargetID:targetID]; + }); } - (void)collectGarbage { - FSTWriteGroup *group = [self.persistence startGroupWithAction:@"Garbage Collection"]; - // Call collectGarbage regardless of whether isGCEnabled so the referenceSet doesn't continue to - // accumulate the garbage keys. - std::set garbage = [self.garbageCollector collectGarbage]; - if (garbage.size() > 0) { - for (const DocumentKey &key : garbage) { - [self.remoteDocumentCache removeEntryForKey:key]; + self.persistence.run("Garbage Collection", [&]() { + // Call collectGarbage regardless of whether isGCEnabled so the referenceSet doesn't continue to + // accumulate the garbage keys. + std::set garbage = [self.garbageCollector collectGarbage]; + if (garbage.size() > 0) { + for (const DocumentKey &key : garbage) { + [self.remoteDocumentCache removeEntryForKey:key]; + } } - } - [self.persistence commitGroup:group]; + }); } /** @@ -481,9 +464,8 @@ NS_ASSUME_NONNULL_BEGIN * * @return the set of keys of docs that were modified by those writes. */ -- (FSTDocumentKeySet *)releaseHeldBatchResultsWithGroup:(FSTWriteGroup *)group - remoteDocuments: - (FSTRemoteDocumentChangeBuffer *)remoteDocuments { +- (FSTDocumentKeySet *)releaseHeldBatchResultsWithRemoteDocuments: + (FSTRemoteDocumentChangeBuffer *)remoteDocuments { NSMutableArray *toRelease = [NSMutableArray array]; for (FSTMutationBatchResult *batchResult in self.heldBatchResults) { if (![self isRemoteUpToVersion:batchResult.commitVersion]) { @@ -496,7 +478,7 @@ NS_ASSUME_NONNULL_BEGIN return [FSTDocumentKeySet keySet]; } else { [self.heldBatchResults removeObjectsInRange:NSMakeRange(0, toRelease.count)]; - return [self releaseBatchResults:toRelease group:group remoteDocuments:remoteDocuments]; + return [self releaseBatchResults:toRelease remoteDocuments:remoteDocuments]; } } @@ -512,7 +494,6 @@ NS_ASSUME_NONNULL_BEGIN } - (FSTDocumentKeySet *)releaseBatchResults:(NSArray *)batchResults - group:(FSTWriteGroup *)group remoteDocuments:(FSTRemoteDocumentChangeBuffer *)remoteDocuments { NSMutableArray *batches = [NSMutableArray array]; for (FSTMutationBatchResult *batchResult in batchResults) { @@ -520,16 +501,15 @@ NS_ASSUME_NONNULL_BEGIN [batches addObject:batchResult.batch]; } - return [self removeMutationBatches:batches group:group]; + return [self removeMutationBatches:batches]; } -- (FSTDocumentKeySet *)removeMutationBatch:(FSTMutationBatch *)batch group:(FSTWriteGroup *)group { - return [self removeMutationBatches:@[ batch ] group:group]; +- (FSTDocumentKeySet *)removeMutationBatch:(FSTMutationBatch *)batch { + return [self removeMutationBatches:@[ batch ]]; } /** Removes all the mutation batches named in the given array. */ -- (FSTDocumentKeySet *)removeMutationBatches:(NSArray *)batches - group:(FSTWriteGroup *)group { +- (FSTDocumentKeySet *)removeMutationBatches:(NSArray *)batches { // TODO(klimt): Could this be an NSMutableDictionary? __block FSTDocumentKeySet *affectedDocs = [FSTDocumentKeySet keySet]; diff --git a/Firestore/Source/Local/FSTMemoryPersistence.mm b/Firestore/Source/Local/FSTMemoryPersistence.mm index f1f9885..8d74881 100644 --- a/Firestore/Source/Local/FSTMemoryPersistence.mm +++ b/Firestore/Source/Local/FSTMemoryPersistence.mm @@ -21,8 +21,6 @@ #import "Firestore/Source/Local/FSTMemoryMutationQueue.h" #import "Firestore/Source/Local/FSTMemoryQueryCache.h" #import "Firestore/Source/Local/FSTMemoryRemoteDocumentCache.h" -#import "Firestore/Source/Local/FSTWriteGroup.h" -#import "Firestore/Source/Local/FSTWriteGroupTracker.h" #import "Firestore/Source/Util/FSTAssert.h" #include "Firestore/core/src/firebase/firestore/auth/user.h" @@ -33,7 +31,6 @@ using firebase::firestore::auth::User; NS_ASSUME_NONNULL_BEGIN @interface FSTMemoryPersistence () -@property(nonatomic, strong, nonnull) FSTWriteGroupTracker *writeGroupTracker; @property(nonatomic, assign, getter=isStarted) BOOL started; @end @@ -62,7 +59,6 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init { if (self = [super init]) { - _writeGroupTracker = [FSTWriteGroupTracker tracker]; _queryCache = [[FSTMemoryQueryCache alloc] init]; _remoteDocumentCache = [[FSTMemoryRemoteDocumentCache alloc] init]; } @@ -103,16 +99,6 @@ NS_ASSUME_NONNULL_BEGIN return _remoteDocumentCache; } -- (FSTWriteGroup *)startGroupWithAction:(NSString *)action { - return [self.writeGroupTracker startGroupWithAction:action]; -} - -- (void)commitGroup:(FSTWriteGroup *)group { - [self.writeGroupTracker endGroup:group]; - - FSTAssert(group.isEmpty, @"Memory persistence shouldn't use write groups: %@", group.action); -} - @end NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Local/FSTPersistence.h b/Firestore/Source/Local/FSTPersistence.h index 1784163..2294ef1 100644 --- a/Firestore/Source/Local/FSTPersistence.h +++ b/Firestore/Source/Local/FSTPersistence.h @@ -19,7 +19,6 @@ #import "Firestore/Source/Util/FSTAssert.h" #include "Firestore/core/src/firebase/firestore/auth/user.h" -@class FSTWriteGroup; @protocol FSTMutationQueue; @protocol FSTQueryCache; @protocol FSTRemoteDocumentCache; @@ -86,28 +85,13 @@ struct FSTTransactionRunner; /** Creates an FSTRemoteDocumentCache representing the persisted cache of remote documents. */ - (id)remoteDocumentCache; -/** - * Creates an FSTWriteGroup with the specified action description. - * - * @param action A description of the action performed by this group, used for logging. - * @return The created group. - */ -- (FSTWriteGroup *)startGroupWithAction:(NSString *)action; - -/** - * Commits all accumulated changes in the given group. If there are no changes this is a no-op. - * - * @param group The group of changes to write as a unit. - */ -- (void)commitGroup:(FSTWriteGroup *)group; - @property(nonatomic, readonly, assign) const FSTTransactionRunner &run; @end @protocol FSTTransactional -- (void)startTransaction; +- (void)startTransaction:(absl::string_view)label; - (void)commitTransaction; @@ -136,14 +120,14 @@ struct FSTTransactionRunner { */ template - auto operator()(F block) const -> + auto operator()(absl::string_view label, F block) const -> typename std::enable_if::value, void>::type { __strong id strongDb = _db; if (!strongDb && _expect_db) { FSTCFail(@"Transaction runner accessed without underlying db when it expected one"); } if (strongDb) { - [strongDb startTransaction]; + [strongDb startTransaction:label]; } block(); if (strongDb) { @@ -152,7 +136,7 @@ struct FSTTransactionRunner { } template - auto operator()(F block) const -> + auto operator()(absl::string_view label, F block) const -> typename std::enable_if::value, decltype(block())>::type { using ReturnT = decltype(block()); __strong id strongDb = _db; @@ -160,7 +144,7 @@ struct FSTTransactionRunner { FSTCFail(@"Transaction runner accessed without underlying db when it expected one"); } if (strongDb) { - [strongDb startTransaction]; + [strongDb startTransaction:label]; } ReturnT result = block(); if (strongDb) { diff --git a/Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.h b/Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.h index cfdf55b..be29a89 100644 --- a/Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.h +++ b/Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.h @@ -22,7 +22,6 @@ NS_ASSUME_NONNULL_BEGIN @protocol FSTRemoteDocumentCache; @class FSTMaybeDocument; -@class FSTWriteGroup; /** * An in-memory buffer of entries to be written to an FSTRemoteDocumentCache. It can be used to @@ -58,10 +57,9 @@ NS_ASSUME_NONNULL_BEGIN (const firebase::firestore::model::DocumentKey &)documentKey; /** - * Applies buffered changes to the underlying FSTRemoteDocumentCache, using the provided - * FSTWriteGroup. + * Applies buffered changes to the underlying FSTRemoteDocumentCache */ -- (void)applyToWriteGroup:(FSTWriteGroup *)group; +- (void)apply; @end diff --git a/Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.mm b/Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.mm index 0557bce..3812501 100644 --- a/Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.mm +++ b/Firestore/Source/Local/FSTRemoteDocumentChangeBuffer.mm @@ -73,7 +73,7 @@ NS_ASSUME_NONNULL_BEGIN } } -- (void)applyToWriteGroup:(FSTWriteGroup *)group { +- (void)apply { [self assertValid]; for (const auto &kv : *_changes) { diff --git a/Firestore/Source/Local/FSTWriteGroup.h b/Firestore/Source/Local/FSTWriteGroup.h deleted file mode 100644 index a554597..0000000 --- a/Firestore/Source/Local/FSTWriteGroup.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#include - -#include "Firestore/Source/Local/StringView.h" -#include "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h" -#include "leveldb/db.h" - -NS_ASSUME_NONNULL_BEGIN - -@class GPBMessage; - -/** - * A group of writes that will be applied together atomically to persistent storage. - * - * This class is usable by both Objective-C and Objective-C++ clients. Objective-C clients are able - * to create a new group and commit it. Objective-C++ clients can additionally add to the group - * using deleteKey: and putKey:value:. - * - * Note that this is a write "group" even though the underlying LevelDB concept is a write "batch" - * because Firestore already has a concept of mutation batches, which are user-specified groups of - * changes. This means that an FSTWriteGroup may contain the application of multiple user-specified - * mutation batches. - */ -@interface FSTWriteGroup : NSObject - -/** - * Creates a new, empty write group. - * - * @param action A description of the action performed by this group, used for logging. - */ -+ (instancetype)groupWithAction:(NSString *)action; - -+ (instancetype)groupWithAction:(NSString *)action - transaction:(firebase::firestore::local::LevelDbTransaction *)transaction; - -- (instancetype)init __attribute__((unavailable("Use a static constructor instead"))); - -/** The action description assigned to this write group. */ -@property(nonatomic, copy, readonly) NSString *action; - -@property(nonatomic, readonly) firebase::firestore::local::LevelDbTransaction *transaction; - -/** - * Marks the given key for deletion. - * - * @param key The LevelDB key of the row to delete - */ -- (void)removeMessageForKey:(Firestore::StringView)key; - -/** - * Sets the row identified by the given key to the value of the given protocol buffer message. - * - * @param key The LevelDB Key of the row to set. - * @param message The protocol buffer message whose serialized contents should be used for the - * value associated with the key. - */ -- (void)setMessage:(GPBMessage *)message forKey:(Firestore::StringView)key; - -/** - * Sets the row identified by the given key to the value of the given data bytes. - * - * @param key The LevelDB Key of the row to set. - * @param data The exact value to be associated with the key. - */ -- (void)setData:(Firestore::StringView)data forKey:(Firestore::StringView)key; - -/** Returns YES if the write group has no messages in it. */ -- (BOOL)isEmpty; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Local/FSTWriteGroup.mm b/Firestore/Source/Local/FSTWriteGroup.mm deleted file mode 100644 index 9aee31a..0000000 --- a/Firestore/Source/Local/FSTWriteGroup.mm +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "Firestore/Source/Local/FSTWriteGroup.h" - -#include - -#import "Firestore/Source/Local/FSTLevelDBKey.h" -#import "Firestore/Source/Util/FSTAssert.h" - -using firebase::firestore::local::LevelDbTransaction; -using Firestore::StringView; -using leveldb::DB; -using leveldb::Slice; -using leveldb::Status; -using leveldb::WriteBatch; -using leveldb::WriteOptions; - -NS_ASSUME_NONNULL_BEGIN - -@interface FSTWriteGroup () -- (instancetype)initWithAction:(NSString *)action NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithAction:(NSString *)action transaction:(LevelDbTransaction *)transaction; -@end - -@implementation FSTWriteGroup { - int _changes; -} - -+ (instancetype)groupWithAction:(NSString *)action { - return [[FSTWriteGroup alloc] initWithAction:action]; -} - -+ (instancetype)groupWithAction:(NSString *)action - transaction:(firebase::firestore::local::LevelDbTransaction *)transaction { - return [[FSTWriteGroup alloc] initWithAction:action transaction:transaction]; -} - -- (instancetype)initWithAction:(NSString *)action { - if (self = [super init]) { - _action = action; - _transaction = nullptr; - } - return self; -} - -- (instancetype)initWithAction:(NSString *)action transaction:(LevelDbTransaction *)transaction { - if (self = [self initWithAction:action]) { - _transaction = transaction; - } - return self; -} - -- (void)removeMessageForKey:(StringView)key { - FSTAssert(_transaction != nullptr, @"Using group without a transaction"); - Slice keySlice = key; - _transaction->Delete(keySlice.ToString()); - _changes += 1; -} - -- (void)setMessage:(GPBMessage *)message forKey:(StringView)key { - FSTAssert(_transaction != nullptr, @"Using group without a transaction"); - Slice keySlice = key; - _transaction->Put(keySlice.ToString(), message); - _changes += 1; -} - -- (void)setData:(StringView)data forKey:(StringView)key { - FSTAssert(_transaction != nullptr, @"Using group without a transaction"); - Slice keySlice = key; - Slice valueSlice = data; - std::string value = valueSlice.ToString(); - _transaction->Put(keySlice.ToString(), value); - _changes += 1; -} - -- (BOOL)isEmpty { - return _changes == 0; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Local/FSTWriteGroupTracker.h b/Firestore/Source/Local/FSTWriteGroupTracker.h deleted file mode 100644 index c4651ab..0000000 --- a/Firestore/Source/Local/FSTWriteGroupTracker.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#import "Firestore/core/src/firebase/firestore/local/leveldb_transaction.h" - -@class FSTWriteGroup; - -NS_ASSUME_NONNULL_BEGIN - -/** - * Helper class for FSTPersistence implementations to create WriteGroups and verify internal - * contracts are maintained: - * 1. Can't create a group when an uncommitted group exists (no nesting). - * 2. Can't commit a group that differs from the last created one. - */ -@interface FSTWriteGroupTracker : NSObject - -/** Creates and returns an FSTWriteGroupTracker instance. */ -+ (instancetype)tracker; - -/** - * Verifies there's no active group already and then creates a new group and stores it for later - * validation with `endGroup`. - */ -- (FSTWriteGroup *)startGroupWithAction:(NSString *)action; - -- (FSTWriteGroup *)startGroupWithAction:(NSString *)action - transaction: - (firebase::firestore::local::LevelDbTransaction *)transaction; - -/** Ends a group previously started with `startGroupWithAction`. */ -- (void)endGroup:(FSTWriteGroup *)group; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Firestore/Source/Local/FSTWriteGroupTracker.mm b/Firestore/Source/Local/FSTWriteGroupTracker.mm deleted file mode 100644 index 2cb10bd..0000000 --- a/Firestore/Source/Local/FSTWriteGroupTracker.mm +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2017 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "Firestore/Source/Local/FSTWriteGroupTracker.h" - -#import "Firestore/Source/Local/FSTWriteGroup.h" -#import "Firestore/Source/Util/FSTAssert.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FSTWriteGroupTracker () -@property(nonatomic, strong, nullable) FSTWriteGroup *activeGroup; -@end - -@implementation FSTWriteGroupTracker - -+ (instancetype)tracker { - return [[FSTWriteGroupTracker alloc] init]; -} - -- (FSTWriteGroup *)startGroupWithAction:(NSString *)action { - // NOTE: We can relax this to allow nesting if/when we find we need it. - FSTAssert(!self.activeGroup, - @"Attempt to create write group (%@) while existing write group (%@) still active.", - action, self.activeGroup.action); - self.activeGroup = [FSTWriteGroup groupWithAction:action]; - return self.activeGroup; -} - -- (FSTWriteGroup *)startGroupWithAction:(NSString *)action - transaction: - (firebase::firestore::local::LevelDbTransaction *)transaction { - // NOTE: We can relax this to allow nesting if/when we find we need it. - FSTAssert(!self.activeGroup, - @"Attempt to create write group (%@) while existing write group (%@) still active.", - action, self.activeGroup.action); - self.activeGroup = [FSTWriteGroup groupWithAction:action transaction:transaction]; - return self.activeGroup; -} - -- (void)endGroup:(FSTWriteGroup *)group { - FSTAssert(self.activeGroup == group, - @"Attempted to end write group (%@) which is different from active group (%@)", - group.action, self.activeGroup.action); - self.activeGroup = nil; -} - -@end - -NS_ASSUME_NONNULL_END -- cgit v1.2.3