FSTMutationBatch.mm 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "Firestore/Source/Model/FSTMutationBatch.h"
  17. #include <algorithm>
  18. #include <utility>
  19. #import "FIRTimestamp.h"
  20. #import "Firestore/Source/Model/FSTDocument.h"
  21. #import "Firestore/Source/Model/FSTMutation.h"
  22. #include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
  23. #include "Firestore/core/src/firebase/firestore/util/hashing.h"
  24. #include "Firestore/core/src/firebase/firestore/util/objc_compatibility.h"
  25. namespace objc = firebase::firestore::util::objc;
  26. using firebase::firestore::model::BatchId;
  27. using firebase::firestore::model::DocumentKey;
  28. using firebase::firestore::model::DocumentKeyHash;
  29. using firebase::firestore::model::DocumentKeySet;
  30. using firebase::firestore::model::DocumentVersionMap;
  31. using firebase::firestore::model::SnapshotVersion;
  32. using firebase::firestore::util::Hash;
  33. NS_ASSUME_NONNULL_BEGIN
  34. @implementation FSTMutationBatch {
  35. std::vector<FSTMutation *> _mutations;
  36. }
  37. - (instancetype)initWithBatchID:(BatchId)batchID
  38. localWriteTime:(FIRTimestamp *)localWriteTime
  39. mutations:(std::vector<FSTMutation *> &&)mutations {
  40. HARD_ASSERT(!mutations.empty(), "Cannot create an empty mutation batch");
  41. self = [super init];
  42. if (self) {
  43. _batchID = batchID;
  44. _localWriteTime = localWriteTime;
  45. _mutations = std::move(mutations);
  46. }
  47. return self;
  48. }
  49. - (const std::vector<FSTMutation *> &)mutations {
  50. return _mutations;
  51. }
  52. - (BOOL)isEqual:(id)other {
  53. if (self == other) {
  54. return YES;
  55. } else if (![other isKindOfClass:[FSTMutationBatch class]]) {
  56. return NO;
  57. }
  58. FSTMutationBatch *otherBatch = (FSTMutationBatch *)other;
  59. return self.batchID == otherBatch.batchID &&
  60. [self.localWriteTime isEqual:otherBatch.localWriteTime] &&
  61. std::equal(_mutations.begin(), _mutations.end(), otherBatch.mutations.begin(),
  62. [](FSTMutation *lhs, FSTMutation *rhs) { return [lhs isEqual:rhs]; });
  63. }
  64. - (NSUInteger)hash {
  65. NSUInteger result = (NSUInteger)self.batchID;
  66. result = result * 31 + self.localWriteTime.hash;
  67. for (FSTMutation *mutation : _mutations) {
  68. result = result * 31 + [mutation hash];
  69. }
  70. return result;
  71. }
  72. - (NSString *)description {
  73. return
  74. [NSString stringWithFormat:@"<FSTMutationBatch: id=%d, localWriteTime=%@, mutations=%@>",
  75. self.batchID, self.localWriteTime, objc::Description(_mutations)];
  76. }
  77. - (FSTMaybeDocument *_Nullable)applyToRemoteDocument:(FSTMaybeDocument *_Nullable)maybeDoc
  78. documentKey:(const DocumentKey &)documentKey
  79. mutationBatchResult:
  80. (FSTMutationBatchResult *_Nullable)mutationBatchResult {
  81. HARD_ASSERT(!maybeDoc || maybeDoc.key == documentKey,
  82. "applyTo: key %s doesn't match maybeDoc key %s", documentKey.ToString(),
  83. maybeDoc.key.ToString());
  84. HARD_ASSERT(mutationBatchResult.mutationResults.size() == _mutations.size(),
  85. "Mismatch between mutations length (%s) and results length (%s)", _mutations.size(),
  86. mutationBatchResult.mutationResults.size());
  87. for (size_t i = 0; i < _mutations.size(); i++) {
  88. FSTMutation *mutation = _mutations[i];
  89. FSTMutationResult *mutationResult = mutationBatchResult.mutationResults[i];
  90. if (mutation.key == documentKey) {
  91. maybeDoc = [mutation applyToRemoteDocument:maybeDoc mutationResult:mutationResult];
  92. }
  93. }
  94. return maybeDoc;
  95. }
  96. - (FSTMaybeDocument *_Nullable)applyToLocalDocument:(FSTMaybeDocument *_Nullable)maybeDoc
  97. documentKey:(const DocumentKey &)documentKey {
  98. HARD_ASSERT(!maybeDoc || maybeDoc.key == documentKey,
  99. "applyTo: key %s doesn't match maybeDoc key %s", documentKey.ToString(),
  100. maybeDoc.key.ToString());
  101. FSTMaybeDocument *baseDoc = maybeDoc;
  102. for (FSTMutation *mutation : _mutations) {
  103. if (mutation.key == documentKey) {
  104. maybeDoc = [mutation applyToLocalDocument:maybeDoc
  105. baseDocument:baseDoc
  106. localWriteTime:self.localWriteTime];
  107. }
  108. }
  109. return maybeDoc;
  110. }
  111. - (DocumentKeySet)keys {
  112. DocumentKeySet set;
  113. for (FSTMutation *mutation : _mutations) {
  114. set = set.insert(mutation.key);
  115. }
  116. return set;
  117. }
  118. @end
  119. #pragma mark - FSTMutationBatchResult
  120. @interface FSTMutationBatchResult ()
  121. - (instancetype)initWithBatch:(FSTMutationBatch *)batch
  122. commitVersion:(SnapshotVersion)commitVersion
  123. mutationResults:(std::vector<FSTMutationResult *>)mutationResults
  124. streamToken:(nullable NSData *)streamToken
  125. docVersions:(DocumentVersionMap)docVersions NS_DESIGNATED_INITIALIZER;
  126. @end
  127. @implementation FSTMutationBatchResult {
  128. SnapshotVersion _commitVersion;
  129. std::vector<FSTMutationResult *> _mutationResults;
  130. DocumentVersionMap _docVersions;
  131. }
  132. - (instancetype)initWithBatch:(FSTMutationBatch *)batch
  133. commitVersion:(SnapshotVersion)commitVersion
  134. mutationResults:(std::vector<FSTMutationResult *>)mutationResults
  135. streamToken:(nullable NSData *)streamToken
  136. docVersions:(DocumentVersionMap)docVersions {
  137. if (self = [super init]) {
  138. _batch = batch;
  139. _commitVersion = std::move(commitVersion);
  140. _mutationResults = std::move(mutationResults);
  141. _streamToken = streamToken;
  142. _docVersions = std::move(docVersions);
  143. }
  144. return self;
  145. }
  146. - (const SnapshotVersion &)commitVersion {
  147. return _commitVersion;
  148. }
  149. - (const std::vector<FSTMutationResult *> &)mutationResults {
  150. return _mutationResults;
  151. }
  152. - (const DocumentVersionMap &)docVersions {
  153. return _docVersions;
  154. }
  155. + (instancetype)resultWithBatch:(FSTMutationBatch *)batch
  156. commitVersion:(SnapshotVersion)commitVersion
  157. mutationResults:(std::vector<FSTMutationResult *>)mutationResults
  158. streamToken:(nullable NSData *)streamToken {
  159. HARD_ASSERT(batch.mutations.size() == mutationResults.size(),
  160. "Mutations sent %s must equal results received %s", batch.mutations.size(),
  161. mutationResults.size());
  162. DocumentVersionMap docVersions;
  163. std::vector<FSTMutation *> mutations = batch.mutations;
  164. for (size_t i = 0; i < mutations.size(); i++) {
  165. absl::optional<SnapshotVersion> version = mutationResults[i].version;
  166. if (!version) {
  167. // deletes don't have a version, so we substitute the commitVersion
  168. // of the entire batch.
  169. version = commitVersion;
  170. }
  171. docVersions[mutations[i].key] = version.value();
  172. }
  173. return [[FSTMutationBatchResult alloc] initWithBatch:batch
  174. commitVersion:std::move(commitVersion)
  175. mutationResults:std::move(mutationResults)
  176. streamToken:streamToken
  177. docVersions:std::move(docVersions)];
  178. }
  179. @end
  180. NS_ASSUME_NONNULL_END