Skip to content

Commit 65f2709

Browse files
author
Greg Soltis
authored
Port FSTMemoryQueryCache to C++ (#2197)
1 parent f39cdf3 commit 65f2709

File tree

3 files changed

+283
-77
lines changed

3 files changed

+283
-77
lines changed

Firestore/Source/Local/FSTMemoryQueryCache.mm

Lines changed: 23 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#import <Protobuf/GPBProtocolBuffers.h>
2020

21+
#include <memory>
2122
#include <utility>
2223

2324
#import "Firestore/Protos/objc/firestore/local/Target.pbobjc.h"
@@ -26,9 +27,12 @@
2627
#import "Firestore/Source/Local/FSTQueryData.h"
2728
#import "Firestore/Source/Local/FSTReferenceSet.h"
2829

30+
#include "Firestore/core/src/firebase/firestore/local/memory_query_cache.h"
2931
#include "Firestore/core/src/firebase/firestore/model/document_key.h"
3032
#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
33+
#include "absl/memory/memory.h"
3134

35+
using firebase::firestore::local::MemoryQueryCache;
3236
using firebase::firestore::model::DocumentKey;
3337
using firebase::firestore::model::DocumentKeySet;
3438
using firebase::firestore::model::ListenSequenceNumber;
@@ -37,33 +41,13 @@
3741

3842
NS_ASSUME_NONNULL_BEGIN
3943

40-
@interface FSTMemoryQueryCache ()
41-
42-
/** Maps a query to the data about that query. */
43-
@property(nonatomic, strong, readonly) NSMutableDictionary<FSTQuery *, FSTQueryData *> *queries;
44-
45-
/** A ordered bidirectional mapping between documents and the remote target IDs. */
46-
@property(nonatomic, strong, readonly) FSTReferenceSet *references;
47-
48-
/** The highest numbered target ID encountered. */
49-
@property(nonatomic, assign) TargetId highestTargetID;
50-
51-
@property(nonatomic, assign) ListenSequenceNumber highestListenSequenceNumber;
52-
53-
@end
54-
5544
@implementation FSTMemoryQueryCache {
56-
FSTMemoryPersistence *_persistence;
57-
/** The last received snapshot version. */
58-
SnapshotVersion _lastRemoteSnapshotVersion;
45+
std::unique_ptr<MemoryQueryCache> _cache;
5946
}
6047

6148
- (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence {
6249
if (self = [super init]) {
63-
_persistence = persistence;
64-
_queries = [NSMutableDictionary dictionary];
65-
_references = [[FSTReferenceSet alloc] init];
66-
_lastRemoteSnapshotVersion = SnapshotVersion::None();
50+
_cache = absl::make_unique<MemoryQueryCache>(persistence);
6751
}
6852
return self;
6953
}
@@ -72,112 +56,74 @@ - (instancetype)initWithPersistence:(FSTMemoryPersistence *)persistence {
7256
#pragma mark Query tracking
7357

7458
- (TargetId)highestTargetID {
75-
return _highestTargetID;
59+
return _cache->highest_target_id();
7660
}
7761

7862
- (ListenSequenceNumber)highestListenSequenceNumber {
79-
return _highestListenSequenceNumber;
63+
return _cache->highest_listen_sequence_number();
8064
}
8165

8266
- (const SnapshotVersion &)lastRemoteSnapshotVersion {
83-
return _lastRemoteSnapshotVersion;
67+
return _cache->last_remote_snapshot_version();
8468
}
8569

8670
- (void)setLastRemoteSnapshotVersion:(SnapshotVersion)snapshotVersion {
87-
_lastRemoteSnapshotVersion = std::move(snapshotVersion);
71+
_cache->set_last_remote_snapshot_version(std::move(snapshotVersion));
8872
}
8973

9074
- (void)addQueryData:(FSTQueryData *)queryData {
91-
self.queries[queryData.query] = queryData;
92-
if (queryData.targetID > self.highestTargetID) {
93-
self.highestTargetID = queryData.targetID;
94-
}
95-
if (queryData.sequenceNumber > self.highestListenSequenceNumber) {
96-
self.highestListenSequenceNumber = queryData.sequenceNumber;
97-
}
75+
_cache->AddTarget(queryData);
9876
}
9977

10078
- (void)updateQueryData:(FSTQueryData *)queryData {
101-
self.queries[queryData.query] = queryData;
102-
if (queryData.targetID > self.highestTargetID) {
103-
self.highestTargetID = queryData.targetID;
104-
}
105-
if (queryData.sequenceNumber > self.highestListenSequenceNumber) {
106-
self.highestListenSequenceNumber = queryData.sequenceNumber;
107-
}
79+
_cache->UpdateTarget(queryData);
10880
}
10981

11082
- (int32_t)count {
111-
return (int32_t)[self.queries count];
83+
return _cache->count();
11284
}
11385

11486
- (void)removeQueryData:(FSTQueryData *)queryData {
115-
[self.queries removeObjectForKey:queryData.query];
116-
[self.references removeReferencesForID:queryData.targetID];
87+
_cache->RemoveTarget(queryData);
11788
}
11889

11990
- (nullable FSTQueryData *)queryDataForQuery:(FSTQuery *)query {
120-
return self.queries[query];
91+
return _cache->GetTarget(query);
12192
}
12293

12394
- (void)enumerateTargetsUsingBlock:(void (^)(FSTQueryData *queryData, BOOL *stop))block {
124-
[self.queries
125-
enumerateKeysAndObjectsUsingBlock:^(FSTQuery *key, FSTQueryData *queryData, BOOL *stop) {
126-
block(queryData, stop);
127-
}];
95+
_cache->EnumerateTargets(block);
12896
}
12997

13098
- (int)removeQueriesThroughSequenceNumber:(ListenSequenceNumber)sequenceNumber
13199
liveQueries:(NSDictionary<NSNumber *, FSTQueryData *> *)liveQueries {
132-
NSMutableArray<FSTQuery *> *toRemove = [NSMutableArray array];
133-
[self.queries
134-
enumerateKeysAndObjectsUsingBlock:^(FSTQuery *query, FSTQueryData *queryData, BOOL *stop) {
135-
if (queryData.sequenceNumber <= sequenceNumber) {
136-
if (liveQueries[@(queryData.targetID)] == nil) {
137-
[toRemove addObject:query];
138-
[self.references removeReferencesForID:queryData.targetID];
139-
}
140-
}
141-
}];
142-
[self.queries removeObjectsForKeys:toRemove];
143-
return (int)[toRemove count];
100+
return _cache->RemoveTargets(sequenceNumber, liveQueries);
144101
}
145102

146103
#pragma mark Reference tracking
147104

148105
- (void)addMatchingKeys:(const DocumentKeySet &)keys forTargetID:(TargetId)targetID {
149-
[self.references addReferencesToKeys:keys forID:targetID];
150-
for (const DocumentKey &key : keys) {
151-
[_persistence.referenceDelegate addReference:key];
152-
}
106+
_cache->AddMatchingKeys(keys, targetID);
153107
}
154108

155109
- (void)removeMatchingKeys:(const DocumentKeySet &)keys forTargetID:(TargetId)targetID {
156-
[self.references removeReferencesToKeys:keys forID:targetID];
157-
for (const DocumentKey &key : keys) {
158-
[_persistence.referenceDelegate removeReference:key];
159-
}
110+
_cache->RemoveMatchingKeys(keys, targetID);
160111
}
161112

162113
- (void)removeMatchingKeysForTargetID:(TargetId)targetID {
163-
[self.references removeReferencesForID:targetID];
114+
_cache->RemoveAllKeysForTarget(targetID);
164115
}
165116

166117
- (DocumentKeySet)matchingKeysForTargetID:(TargetId)targetID {
167-
return [self.references referencedKeysForID:targetID];
118+
return _cache->GetMatchingKeys(targetID);
168119
}
169120

170121
- (BOOL)containsKey:(const firebase::firestore::model::DocumentKey &)key {
171-
return [self.references containsKey:key];
122+
return _cache->Contains(key);
172123
}
173124

174125
- (size_t)byteSizeWithSerializer:(FSTLocalSerializer *)serializer {
175-
__block size_t count = 0;
176-
[self.queries
177-
enumerateKeysAndObjectsUsingBlock:^(FSTQuery *key, FSTQueryData *queryData, BOOL *stop) {
178-
count += [[serializer encodedQueryData:queryData] serializedSize];
179-
}];
180-
return count;
126+
return _cache->CalculateByteSize(serializer);
181127
}
182128

183129
@end
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/*
2+
* Copyright 2018 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+
17+
#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_LOCAL_MEMORY_QUERY_CACHE_H_
18+
#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_LOCAL_MEMORY_QUERY_CACHE_H_
19+
20+
#if !defined(__OBJC__)
21+
#error "For now, this file must only be included by ObjC source files."
22+
#endif // !defined(__OBJC__)
23+
24+
#import <Foundation/Foundation.h>
25+
26+
#include <cstdint>
27+
#include <utility>
28+
29+
#include "Firestore/core/src/firebase/firestore/model/document_key_set.h"
30+
#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
31+
#include "Firestore/core/src/firebase/firestore/model/types.h"
32+
33+
@class FSTLocalSerializer;
34+
@class FSTMemoryPersistence;
35+
@class FSTQuery;
36+
@class FSTQueryData;
37+
@class FSTReferenceSet;
38+
39+
NS_ASSUME_NONNULL_BEGIN
40+
41+
namespace firebase {
42+
namespace firestore {
43+
namespace local {
44+
45+
typedef void (^TargetEnumerator)(FSTQueryData*, BOOL*);
46+
47+
class MemoryQueryCache {
48+
public:
49+
explicit MemoryQueryCache(FSTMemoryPersistence* persistence);
50+
51+
// Target-related methods
52+
void AddTarget(FSTQueryData* query_data);
53+
54+
void UpdateTarget(FSTQueryData* query_data);
55+
56+
void RemoveTarget(FSTQueryData* query_data);
57+
58+
FSTQueryData* _Nullable GetTarget(FSTQuery* query);
59+
60+
void EnumerateTargets(TargetEnumerator block);
61+
62+
int RemoveTargets(model::ListenSequenceNumber upper_bound,
63+
NSDictionary<NSNumber*, FSTQueryData*>* live_targets);
64+
65+
// Key-related methods
66+
void AddMatchingKeys(const model::DocumentKeySet& keys,
67+
model::TargetId target_id);
68+
69+
void RemoveMatchingKeys(const model::DocumentKeySet& keys,
70+
model::TargetId target_id);
71+
72+
void RemoveAllKeysForTarget(model::TargetId target_id);
73+
74+
model::DocumentKeySet GetMatchingKeys(model::TargetId target_id);
75+
76+
bool Contains(const model::DocumentKey& key);
77+
78+
// Other methods and accessors
79+
size_t CalculateByteSize(FSTLocalSerializer* serializer);
80+
81+
int32_t count() const {
82+
return static_cast<int32_t>([queries_ count]);
83+
}
84+
85+
model::ListenSequenceNumber highest_listen_sequence_number() const {
86+
return highest_listen_sequence_number_;
87+
}
88+
89+
model::TargetId highest_target_id() const {
90+
return highest_target_id_;
91+
}
92+
93+
const model::SnapshotVersion& last_remote_snapshot_version() const {
94+
return last_remote_snapshot_version_;
95+
}
96+
97+
void set_last_remote_snapshot_version(model::SnapshotVersion version) {
98+
last_remote_snapshot_version_ = std::move(version);
99+
}
100+
101+
private:
102+
FSTMemoryPersistence* persistence_;
103+
/** The highest sequence number encountered */
104+
model::ListenSequenceNumber highest_listen_sequence_number_;
105+
/** The highest numbered target ID encountered. */
106+
model::TargetId highest_target_id_;
107+
/** The last received snapshot version. */
108+
model::SnapshotVersion last_remote_snapshot_version_;
109+
110+
/** Maps a query to the data about that query. */
111+
NSMutableDictionary<FSTQuery*, FSTQueryData*>* queries_;
112+
/** A ordered bidirectional mapping between documents and the remote target
113+
* IDs. */
114+
FSTReferenceSet* references_;
115+
};
116+
117+
} // namespace local
118+
} // namespace firestore
119+
} // namespace firebase
120+
121+
NS_ASSUME_NONNULL_END
122+
123+
#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_LOCAL_MEMORY_QUERY_CACHE_H_

0 commit comments

Comments
 (0)