@@ -60,7 +60,7 @@ absl::optional<Overlay> LevelDbDocumentOverlayCache::GetOverlay(
60
60
auto it = db_->current_transaction ()->NewIterator ();
61
61
it->Seek (key_prefix);
62
62
63
- if (!( it->Valid () && absl::StartsWith (it->key (), key_prefix) )) {
63
+ if (!it->Valid () || ! absl::StartsWith (it->key (), key_prefix)) {
64
64
return absl::nullopt;
65
65
}
66
66
@@ -88,28 +88,13 @@ void LevelDbDocumentOverlayCache::RemoveOverlaysForBatchId(int batch_id) {
88
88
DocumentOverlayCache::OverlayByDocumentKeyMap
89
89
LevelDbDocumentOverlayCache::GetOverlays (const ResourcePath& collection,
90
90
int since_batch_id) const {
91
- // TODO(dconeybe) Implement an index so that this query can be performed
92
- // without requiring a full table scan.
93
-
94
91
OverlayByDocumentKeyMap result;
95
-
96
- const size_t immediate_children_path_length{collection.size () + 1 };
97
-
98
- ForEachOverlay ([&](LevelDbDocumentOverlayKey&& key,
99
- absl::string_view encoded_mutation) {
100
- if (!collection.IsPrefixOf (key.document_key ().path ())) {
101
- return ;
102
- }
103
- // Documents from sub-collections
104
- if (key.document_key ().path ().size () != immediate_children_path_length) {
105
- return ;
106
- }
107
-
108
- if (key.largest_batch_id () > since_batch_id) {
109
- result[key.document_key ()] = ParseOverlay (key, encoded_mutation);
110
- }
111
- });
112
-
92
+ ForEachKeyInCollection (
93
+ collection, since_batch_id, [&](LevelDbDocumentOverlayKey&& key) {
94
+ absl::optional<Overlay> overlay = GetOverlay (key);
95
+ HARD_ASSERT (overlay.has_value ());
96
+ result[std::move (key).document_key ()] = std::move (overlay).value ();
97
+ });
113
98
return result;
114
99
}
115
100
@@ -167,6 +152,11 @@ int LevelDbDocumentOverlayCache::GetLargestBatchIdIndexEntryCount() const {
167
152
LevelDbDocumentOverlayLargestBatchIdIndexKey::KeyPrefix (user_id_));
168
153
}
169
154
155
+ int LevelDbDocumentOverlayCache::GetCollectionIndexEntryCount () const {
156
+ return CountEntriesWithKeyPrefix (
157
+ LevelDbDocumentOverlayCollectionIndexKey::KeyPrefix (user_id_));
158
+ }
159
+
170
160
int LevelDbDocumentOverlayCache::CountEntriesWithKeyPrefix (
171
161
const std::string& key_prefix) const {
172
162
int count = 0 ;
@@ -202,6 +192,7 @@ void LevelDbDocumentOverlayCache::SaveOverlay(int largest_batch_id,
202
192
auto * transaction = db_->current_transaction ();
203
193
transaction->Put (key.Encode (), serializer_->EncodeMutation (mutation));
204
194
transaction->Put (LevelDbDocumentOverlayLargestBatchIdIndexKey::Key (key), " " );
195
+ transaction->Put (LevelDbDocumentOverlayCollectionIndexKey::Key (key), " " );
205
196
}
206
197
207
198
void LevelDbDocumentOverlayCache::DeleteOverlay (
@@ -211,7 +202,7 @@ void LevelDbDocumentOverlayCache::DeleteOverlay(
211
202
auto it = db_->current_transaction ()->NewIterator ();
212
203
it->Seek (key_prefix);
213
204
214
- if (!( it->Valid () && absl::StartsWith (it->key (), key_prefix) )) {
205
+ if (!it->Valid () || ! absl::StartsWith (it->key (), key_prefix)) {
215
206
return ;
216
207
}
217
208
@@ -227,6 +218,7 @@ void LevelDbDocumentOverlayCache::DeleteOverlay(
227
218
auto * transaction = db_->current_transaction ();
228
219
transaction->Delete (key.Encode ());
229
220
transaction->Delete (LevelDbDocumentOverlayLargestBatchIdIndexKey::Key (key));
221
+ transaction->Delete (LevelDbDocumentOverlayCollectionIndexKey::Key (key));
230
222
}
231
223
232
224
void LevelDbDocumentOverlayCache::ForEachOverlay (
@@ -258,6 +250,40 @@ void LevelDbDocumentOverlayCache::ForEachKeyWithLargestBatchId(
258
250
}
259
251
}
260
252
253
+ void LevelDbDocumentOverlayCache::ForEachKeyInCollection (
254
+ const ResourcePath& collection,
255
+ int since_batch_id,
256
+ std::function<void (LevelDbDocumentOverlayKey&&)> callback) const {
257
+ const std::string index_start_key =
258
+ LevelDbDocumentOverlayCollectionIndexKey::KeyPrefix (user_id_, collection,
259
+ since_batch_id + 1 );
260
+ const std::string index_key_prefix =
261
+ LevelDbDocumentOverlayCollectionIndexKey::KeyPrefix (user_id_, collection);
262
+
263
+ auto it = db_->current_transaction ()->NewIterator ();
264
+ for (it->Seek (index_start_key);
265
+ it->Valid () && absl::StartsWith (it->key (), index_key_prefix);
266
+ it->Next ()) {
267
+ LevelDbDocumentOverlayCollectionIndexKey key;
268
+ HARD_ASSERT (key.Decode (it->key ()));
269
+ if (key.collection () != collection) {
270
+ break ;
271
+ }
272
+ callback (std::move (key).ToLevelDbDocumentOverlayKey ());
273
+ }
274
+ }
275
+
276
+ absl::optional<Overlay> LevelDbDocumentOverlayCache::GetOverlay (
277
+ const LevelDbDocumentOverlayKey& key) const {
278
+ auto it = db_->current_transaction ()->NewIterator ();
279
+ const std::string encoded_key = key.Encode ();
280
+ it->Seek (encoded_key);
281
+ if (!it->Valid () || it->key () != encoded_key) {
282
+ return absl::nullopt;
283
+ }
284
+ return ParseOverlay (key, it->value ());
285
+ }
286
+
261
287
} // namespace local
262
288
} // namespace firestore
263
289
} // namespace firebase
0 commit comments