FSTMutationBatch.mm 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. using firebase::firestore::model::BatchId;
  25. using firebase::firestore::model::DocumentKey;
  26. using firebase::firestore::model::DocumentKeyHash;
  27. using firebase::firestore::model::DocumentKeySet;
  28. using firebase::firestore::model::DocumentVersionMap;
  29. using firebase::firestore::model::SnapshotVersion;
  30. using firebase::firestore::util::Hash;
  31. NS_ASSUME_NONNULL_BEGIN
  32. @implementation FSTMutationBatch {
  33. std::vector<FSTMutation *> _mutations;
  34. }
  35. - (instancetype)initWithBatchID:(BatchId)batchID
  36. localWriteTime:(FIRTimestamp *)localWriteTime
  37. mutations:(std::vector<FSTMutation *> &&)mutations {
  38. HARD_ASSERT(!mutations.empty(), "Cannot create an empty mutation batch");
  39. self = [super init];
  40. if (self) {
  41. _batchID = batchID;
  42. _localWriteTime = localWriteTime;
  43. _mutations = std::move(mutations);
  44. }
  45. return self;
  46. }
  47. - (const std::vector<FSTMutation *> &)mutations {
  48. return _mutations;
  49. }
  50. - (BOOL)isEqual:(id)other {
  51. if (self == other) {
  52. return YES;
  53. } else if (![other isKindOfClass:[FSTMutationBatch class]]) {
  54. return NO;
  55. }
  56. FSTMutationBatch *otherBatch = (FSTMutationBatch *)other;
  57. return self.batchID == otherBatch.batchID &&
  58. [self.localWriteTime isEqual:otherBatch.localWriteTime] &&
  59. std::equal(_mutations.begin(), _mutations.end(), otherBatch.mutations.begin(),
  60. [](FSTMutation *lhs, FSTMutation *rhs) { return [lhs isEqual:rhs]; });
  61. }
  62. - (NSUInteger)hash {
  63. NSUInteger result = (NSUInteger)self.batchID;
  64. result = result * 31 + self.localWriteTime.hash;
  65. for (FSTMutation *mutation : _mutations) {
  66. result = result * 31 + [mutation hash];
  67. }
  68. return result;
  69. }
  70. - (NSString *)description {
  71. // TODO(varconst): quick-and-dirty-way to create a readable description.
  72. NSMutableArray *mutationsCopy = [NSMutableArray array];
  73. for (FSTMutation *mutation : _mutations) {
  74. [mutationsCopy addObject:mutation];
  75. }
  76. return [NSString stringWithFormat:@"<FSTMutationBatch: id=%d, localWriteTime=%@, mutations=%@>",
  77. self.batchID, self.localWriteTime, mutationsCopy];
  78. }
  79. - (FSTMaybeDocument *_Nullable)applyToRemoteDocument:(FSTMaybeDocument *_Nullable)maybeDoc
  80. documentKey:(const DocumentKey &)documentKey
  81. mutationBatchResult:
  82. (FSTMutationBatchResult *_Nullable)mutationBatchResult {
  83. HARD_ASSERT(!maybeDoc || maybeDoc.key == documentKey,
  84. "applyTo: key %s doesn't match maybeDoc key %s", documentKey.ToString(),
  85. maybeDoc.key.ToString());
  86. HARD_ASSERT(mutationBatchResult.mutationResults.size() == _mutations.size(),
  87. "Mismatch between mutations length (%s) and results length (%s)", _mutations.size(),
  88. mutationBatchResult.mutationResults.size());
  89. for (int i = 0; i < _mutations.size(); i++) {
  90. FSTMutation *mutation = _mutations[i];
  91. FSTMutationResult *mutationResult = mutationBatchResult.mutationResults[i];
  92. if (mutation.key == documentKey) {
  93. maybeDoc = [mutation applyToRemoteDocument:maybeDoc mutationResult:mutationResult];
  94. }
  95. }
  96. return maybeDoc;
  97. }
  98. - (FSTMaybeDocument *_Nullable)applyToLocalDocument:(FSTMaybeDocument *_Nullable)maybeDoc
  99. documentKey:(const DocumentKey &)documentKey {
  100. HARD_ASSERT(!maybeDoc || maybeDoc.key == documentKey,
  101. "applyTo: key %s doesn't match maybeDoc key %s", documentKey.ToString(),
  102. maybeDoc.key.ToString());
  103. FSTMaybeDocument *baseDoc = maybeDoc;
  104. for (FSTMutation *mutation : _mutations) {
  105. if (mutation.key == documentKey) {
  106. maybeDoc = [mutation applyToLocalDocument:maybeDoc
  107. baseDocument:baseDoc
  108. localWriteTime:self.localWriteTime];
  109. }
  110. }
  111. return maybeDoc;
  112. }
  113. - (DocumentKeySet)keys {
  114. DocumentKeySet set;
  115. for (FSTMutation *mutation : _mutations) {
  116. set = set.insert(mutation.key);
  117. }
  118. return set;
  119. }
  120. @end
  121. #pragma mark - FSTMutationBatchResult
  122. @interface FSTMutationBatchResult ()
  123. - (instancetype)initWithBatch:(FSTMutationBatch *)batch
  124. commitVersion:(SnapshotVersion)commitVersion
  125. mutationResults:(std::vector<FSTMutationResult *>)mutationResults
  126. streamToken:(nullable NSData *)streamToken
  127. docVersions:(DocumentVersionMap)docVersions NS_DESIGNATED_INITIALIZER;
  128. @end
  129. @implementation FSTMutationBatchResult {
  130. SnapshotVersion _commitVersion;
  131. std::vector<FSTMutationResult *> _mutationResults;
  132. DocumentVersionMap _docVersions;
  133. }
  134. - (instancetype)initWithBatch:(FSTMutationBatch *)batch
  135. commitVersion:(SnapshotVersion)commitVersion
  136. mutationResults:(std::vector<FSTMutationResult *>)mutationResults
  137. streamToken:(nullable NSData *)streamToken
  138. docVersions:(DocumentVersionMap)docVersions {
  139. if (self = [super init]) {
  140. _batch = batch;
  141. _commitVersion = std::move(commitVersion);
  142. _mutationResults = std::move(mutationResults);
  143. _streamToken = streamToken;
  144. _docVersions = std::move(docVersions);
  145. }
  146. return self;
  147. }
  148. - (const SnapshotVersion &)commitVersion {
  149. return _commitVersion;
  150. }
  151. - (const std::vector<FSTMutationResult *> &)mutationResults {
  152. return _mutationResults;
  153. }
  154. - (const DocumentVersionMap &)docVersions {
  155. return _docVersions;
  156. }
  157. + (instancetype)resultWithBatch:(FSTMutationBatch *)batch
  158. commitVersion:(SnapshotVersion)commitVersion
  159. mutationResults:(std::vector<FSTMutationResult *>)mutationResults
  160. streamToken:(nullable NSData *)streamToken {
  161. HARD_ASSERT(batch.mutations.size() == mutationResults.size(),
  162. "Mutations sent %s must equal results received %s", batch.mutations.size(),
  163. mutationResults.size());
  164. DocumentVersionMap docVersions;
  165. std::vector<FSTMutation *> mutations = batch.mutations;
  166. for (int i = 0; i < mutations.size(); i++) {
  167. absl::optional<SnapshotVersion> version = mutationResults[i].version;
  168. if (!version) {
  169. // deletes don't have a version, so we substitute the commitVersion
  170. // of the entire batch.
  171. version = commitVersion;
  172. }
  173. docVersions[mutations[i].key] = version.value();
  174. }
  175. return [[FSTMutationBatchResult alloc] initWithBatch:batch
  176. commitVersion:std::move(commitVersion)
  177. mutationResults:std::move(mutationResults)
  178. streamToken:streamToken
  179. docVersions:std::move(docVersions)];
  180. }
  181. @end
  182. NS_ASSUME_NONNULL_END