Skip to content

Commit 13e2ed8

Browse files
committed
Add counter
1 parent b1f2130 commit 13e2ed8

File tree

7 files changed

+122
-29
lines changed

7 files changed

+122
-29
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.google.firebase.firestore.local;
2+
3+
public class AutoIndexing {
4+
AutoIndexing() {}
5+
6+
int fullScanCount = 0;
7+
}

firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalDocumentsView.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,16 @@ Document getDocument(DocumentKey key) {
102102
* <p>If we don't have cached state for a document in {@code keys}, a NoDocument will be stored
103103
* for that key in the resulting set.
104104
*/
105-
ImmutableSortedMap<DocumentKey, Document> getDocuments(Iterable<DocumentKey> keys) {
106-
Map<DocumentKey, MutableDocument> docs = remoteDocumentCache.getAll(keys);
105+
ImmutableSortedMap<DocumentKey, Document> getDocuments(
106+
Iterable<DocumentKey> keys, AutoIndexing counter) {
107+
Map<DocumentKey, MutableDocument> docs = remoteDocumentCache.getAll(keys, counter);
107108
return getLocalViewOfDocuments(docs, new HashSet<>());
108109
}
109110

111+
ImmutableSortedMap<DocumentKey, Document> getDocuments(Iterable<DocumentKey> keys) {
112+
return getDocuments(keys, new AutoIndexing());
113+
}
114+
110115
/**
111116
* Similar to {@link #getDocuments}, but creates the local view from the given {@code baseDocs}
112117
* without retrieving documents from the local store.
@@ -260,20 +265,26 @@ void recalculateAndSaveOverlays(Set<DocumentKey> documentKeys) {
260265
* @param offset Read time and key to start scanning by (exclusive).
261266
*/
262267
ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
263-
Query query, IndexOffset offset) {
268+
Query query, IndexOffset offset, AutoIndexing counter) {
264269
ResourcePath path = query.getPath();
265270
if (query.isDocumentQuery()) {
266-
return getDocumentsMatchingDocumentQuery(path);
271+
return getDocumentsMatchingDocumentQuery(path, counter);
267272
} else if (query.isCollectionGroupQuery()) {
268-
return getDocumentsMatchingCollectionGroupQuery(query, offset);
273+
return getDocumentsMatchingCollectionGroupQuery(query, offset, counter);
269274
} else {
270-
return getDocumentsMatchingCollectionQuery(query, offset);
275+
return getDocumentsMatchingCollectionQuery(query, offset, counter);
271276
}
272277
}
273278

279+
ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
280+
Query query, IndexOffset offset) {
281+
return getDocumentsMatchingQuery(query, offset, new AutoIndexing());
282+
}
283+
274284
/** Performs a simple document lookup for the given path. */
275285
private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingDocumentQuery(
276-
ResourcePath path) {
286+
ResourcePath path, AutoIndexing counter) {
287+
counter.fullScanCount++;
277288
ImmutableSortedMap<DocumentKey, Document> result = emptyDocumentMap();
278289
// Just do a simple document lookup.
279290
Document doc = getDocument(DocumentKey.fromPath(path));
@@ -284,7 +295,7 @@ private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingDocumentQu
284295
}
285296

286297
private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollectionGroupQuery(
287-
Query query, IndexOffset offset) {
298+
Query query, IndexOffset offset, AutoIndexing counter) {
288299
hardAssert(
289300
query.getPath().isEmpty(),
290301
"Currently we only support collection group queries at the root.");
@@ -297,7 +308,7 @@ private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollection
297308
for (ResourcePath parent : parents) {
298309
Query collectionQuery = query.asCollectionQueryAtPath(parent.append(collectionId));
299310
ImmutableSortedMap<DocumentKey, Document> collectionResults =
300-
getDocumentsMatchingCollectionQuery(collectionQuery, offset);
311+
getDocumentsMatchingCollectionQuery(collectionQuery, offset, counter);
301312
for (Map.Entry<DocumentKey, Document> docEntry : collectionResults) {
302313
results = results.insert(docEntry.getKey(), docEntry.getValue());
303314
}
@@ -362,11 +373,11 @@ private void populateOverlays(Map<DocumentKey, Overlay> overlays, Set<DocumentKe
362373
}
363374

364375
private ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingCollectionQuery(
365-
Query query, IndexOffset offset) {
376+
Query query, IndexOffset offset, AutoIndexing counter) {
366377
Map<DocumentKey, Overlay> overlays =
367378
documentOverlayCache.getOverlays(query.getPath(), offset.getLargestBatchId());
368379
Map<DocumentKey, MutableDocument> remoteDocuments =
369-
remoteDocumentCache.getDocumentsMatchingQuery(query, offset, overlays.keySet());
380+
remoteDocumentCache.getDocumentsMatchingQuery(query, offset, overlays.keySet(), counter);
370381

371382
// As documents might match the query because of their overlay we need to include documents
372383
// for all overlays in the initial document set.

firebase-firestore/src/main/java/com/google/firebase/firestore/local/MemoryRemoteDocumentCache.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,20 @@ public MutableDocument get(DocumentKey key) {
8080
}
8181

8282
@Override
83-
public Map<DocumentKey, MutableDocument> getAll(Iterable<DocumentKey> keys) {
83+
public Map<DocumentKey, MutableDocument> getAll(
84+
Iterable<DocumentKey> keys, AutoIndexing counter) {
8485
Map<DocumentKey, MutableDocument> result = new HashMap<>();
8586
for (DocumentKey key : keys) {
8687
result.put(key, get(key));
8788
}
8889
return result;
8990
}
9091

92+
@Override
93+
public Map<DocumentKey, MutableDocument> getAll(Iterable<DocumentKey> keys) {
94+
return getAll(keys, new AutoIndexing());
95+
}
96+
9197
@Override
9298
public Map<DocumentKey, MutableDocument> getAll(
9399
String collectionGroup, IndexOffset offset, int limit) {
@@ -97,7 +103,10 @@ public Map<DocumentKey, MutableDocument> getAll(
97103

98104
@Override
99105
public Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
100-
Query query, IndexOffset offset, @Nonnull Set<DocumentKey> mutatedKeys) {
106+
Query query,
107+
IndexOffset offset,
108+
@Nonnull Set<DocumentKey> mutatedKeys,
109+
AutoIndexing counter) {
101110
Map<DocumentKey, MutableDocument> result = new HashMap<>();
102111

103112
// Documents are ordered by key, so we can use a prefix scan to narrow down the documents
@@ -135,6 +144,12 @@ public Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
135144
return result;
136145
}
137146

147+
@Override
148+
public Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
149+
Query query, IndexOffset offset, @Nonnull Set<DocumentKey> mutatedKeys) {
150+
return getDocumentsMatchingQuery(query, offset, mutatedKeys, new AutoIndexing());
151+
}
152+
138153
Iterable<Document> getDocuments() {
139154
return new DocumentIterable();
140155
}

firebase-firestore/src/main/java/com/google/firebase/firestore/local/QueryEngine.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,13 @@ public ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
8282
return result;
8383
}
8484

85-
result = performQueryUsingRemoteKeys(query, remoteKeys, lastLimboFreeSnapshotVersion);
85+
AutoIndexing counter = new AutoIndexing();
86+
result = performQueryUsingRemoteKeys(query, remoteKeys, lastLimboFreeSnapshotVersion, counter);
8687
if (result != null) {
8788
return result;
8889
}
89-
90-
return executeFullCollectionScan(query);
90+
counter = new AutoIndexing();
91+
return executeFullCollectionScan(query, counter);
9192
}
9293

9394
/**
@@ -144,7 +145,8 @@ public ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
144145
private @Nullable ImmutableSortedMap<DocumentKey, Document> performQueryUsingRemoteKeys(
145146
Query query,
146147
ImmutableSortedSet<DocumentKey> remoteKeys,
147-
SnapshotVersion lastLimboFreeSnapshotVersion) {
148+
SnapshotVersion lastLimboFreeSnapshotVersion,
149+
AutoIndexing counter) {
148150
if (query.matchesAllDocuments()) {
149151
// Don't use indexes for queries that can be executed by scanning the collection.
150152
return null;
@@ -157,7 +159,7 @@ public ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
157159
}
158160

159161
ImmutableSortedMap<DocumentKey, Document> documents =
160-
localDocumentsView.getDocuments(remoteKeys);
162+
localDocumentsView.getDocuments(remoteKeys, counter);
161163
ImmutableSortedSet<Document> previousResults = applyQuery(query, documents);
162164

163165
if (needsRefill(query, remoteKeys.size(), previousResults, lastLimboFreeSnapshotVersion)) {
@@ -176,7 +178,8 @@ public ImmutableSortedMap<DocumentKey, Document> getDocumentsMatchingQuery(
176178
previousResults,
177179
query,
178180
IndexOffset.createSuccessor(
179-
lastLimboFreeSnapshotVersion, FieldIndex.INITIAL_LARGEST_BATCH_ID));
181+
lastLimboFreeSnapshotVersion, FieldIndex.INITIAL_LARGEST_BATCH_ID),
182+
counter);
180183
}
181184

182185
/** Applies the query filter and sorting to the provided documents. */
@@ -241,25 +244,31 @@ private boolean needsRefill(
241244
|| documentAtLimitEdge.getVersion().compareTo(limboFreeSnapshotVersion) > 0;
242245
}
243246

244-
private ImmutableSortedMap<DocumentKey, Document> executeFullCollectionScan(Query query) {
247+
private ImmutableSortedMap<DocumentKey, Document> executeFullCollectionScan(
248+
Query query, AutoIndexing counter) {
245249
if (Logger.isDebugEnabled()) {
246250
Logger.debug(LOG_TAG, "Using full collection scan to execute query: %s", query.toString());
247251
}
248-
return localDocumentsView.getDocumentsMatchingQuery(query, IndexOffset.NONE);
252+
return localDocumentsView.getDocumentsMatchingQuery(query, IndexOffset.NONE, counter);
249253
}
250254

251255
/**
252256
* Combines the results from an indexed execution with the remaining documents that have not yet
253257
* been indexed.
254258
*/
255259
private ImmutableSortedMap<DocumentKey, Document> appendRemainingResults(
256-
Iterable<Document> indexedResults, Query query, IndexOffset offset) {
260+
Iterable<Document> indexedResults, Query query, IndexOffset offset, AutoIndexing counter) {
257261
// Retrieve all results for documents that were updated since the offset.
258262
ImmutableSortedMap<DocumentKey, Document> remainingResults =
259-
localDocumentsView.getDocumentsMatchingQuery(query, offset);
263+
localDocumentsView.getDocumentsMatchingQuery(query, offset, counter);
260264
for (Document entry : indexedResults) {
261265
remainingResults = remainingResults.insert(entry.getKey(), entry);
262266
}
263267
return remainingResults;
264268
}
269+
270+
private ImmutableSortedMap<DocumentKey, Document> appendRemainingResults(
271+
Iterable<Document> indexedResults, Query query, IndexOffset offset) {
272+
return appendRemainingResults(indexedResults, query, offset, new AutoIndexing());
273+
}
265274
}

firebase-firestore/src/main/java/com/google/firebase/firestore/local/RemoteDocumentCache.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ interface RemoteDocumentCache {
6767
*/
6868
Map<DocumentKey, MutableDocument> getAll(Iterable<DocumentKey> documentKeys);
6969

70+
Map<DocumentKey, MutableDocument> getAll(
71+
Iterable<DocumentKey> documentKeys, AutoIndexing counter);
72+
7073
/**
7174
* Looks up the next {@code limit} documents for a collection group based on the provided offset.
7275
* The ordering is based on the document's read time and key.
@@ -89,4 +92,7 @@ interface RemoteDocumentCache {
8992
*/
9093
Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
9194
Query query, IndexOffset offset, @Nonnull Set<DocumentKey> mutatedKeys);
95+
96+
Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
97+
Query query, IndexOffset offset, @Nonnull Set<DocumentKey> mutatedKeys, AutoIndexing counter);
9298
}

firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteRemoteDocumentCache.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ public MutableDocument get(DocumentKey documentKey) {
117117
}
118118

119119
@Override
120-
public Map<DocumentKey, MutableDocument> getAll(Iterable<DocumentKey> documentKeys) {
120+
public Map<DocumentKey, MutableDocument> getAll(
121+
Iterable<DocumentKey> documentKeys, AutoIndexing counter) {
121122
Map<DocumentKey, MutableDocument> results = new HashMap<>();
122123
List<Object> bindVars = new ArrayList<>();
123124
for (DocumentKey key : documentKeys) {
@@ -140,12 +141,19 @@ public Map<DocumentKey, MutableDocument> getAll(Iterable<DocumentKey> documentKe
140141
while (longQuery.hasMoreSubqueries()) {
141142
longQuery
142143
.performNextSubquery()
143-
.forEach(row -> processRowInBackground(backgroundQueue, results, row, /*filter*/ null));
144+
.forEach(
145+
row ->
146+
processRowInBackground(backgroundQueue, results, row, /*filter*/ null, counter));
144147
}
145148
backgroundQueue.drain();
146149
return results;
147150
}
148151

152+
@Override
153+
public Map<DocumentKey, MutableDocument> getAll(Iterable<DocumentKey> documentKeys) {
154+
return getAll(documentKeys, new AutoIndexing());
155+
}
156+
149157
@Override
150158
public Map<DocumentKey, MutableDocument> getAll(
151159
String collectionGroup, IndexOffset offset, int limit) {
@@ -182,7 +190,8 @@ private Map<DocumentKey, MutableDocument> getAll(
182190
List<ResourcePath> collections,
183191
IndexOffset offset,
184192
int count,
185-
@Nullable Function<MutableDocument, Boolean> filter) {
193+
@Nullable Function<MutableDocument, Boolean> filter,
194+
AutoIndexing counter) {
186195
Timestamp readTime = offset.getReadTime().getTimestamp();
187196
DocumentKey documentKey = offset.getDocumentKey();
188197

@@ -218,16 +227,25 @@ private Map<DocumentKey, MutableDocument> getAll(
218227
Map<DocumentKey, MutableDocument> results = new HashMap<>();
219228
db.query(sql.toString())
220229
.binding(bindVars)
221-
.forEach(row -> processRowInBackground(backgroundQueue, results, row, filter));
230+
.forEach(row -> processRowInBackground(backgroundQueue, results, row, filter, counter));
222231
backgroundQueue.drain();
223232
return results;
224233
}
225234

235+
private Map<DocumentKey, MutableDocument> getAll(
236+
List<ResourcePath> collections,
237+
IndexOffset offset,
238+
int count,
239+
@Nullable Function<MutableDocument, Boolean> filter) {
240+
return getAll(collections, offset, count, filter, new AutoIndexing());
241+
}
242+
226243
private void processRowInBackground(
227244
BackgroundQueue backgroundQueue,
228245
Map<DocumentKey, MutableDocument> results,
229246
Cursor row,
230-
@Nullable Function<MutableDocument, Boolean> filter) {
247+
@Nullable Function<MutableDocument, Boolean> filter,
248+
AutoIndexing counter) {
231249
byte[] rawDocument = row.getBlob(0);
232250
int readTimeSeconds = row.getInt(1);
233251
int readTimeNanos = row.getInt(2);
@@ -239,6 +257,7 @@ private void processRowInBackground(
239257
() -> {
240258
MutableDocument document =
241259
decodeMaybeDocument(rawDocument, readTimeSeconds, readTimeNanos);
260+
counter.fullScanCount++;
242261
if (filter == null || filter.apply(document)) {
243262
synchronized (results) {
244263
results.put(document.getKey(), document);
@@ -250,11 +269,21 @@ private void processRowInBackground(
250269
@Override
251270
public Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
252271
Query query, IndexOffset offset, @Nonnull Set<DocumentKey> mutatedKeys) {
272+
return getDocumentsMatchingQuery(query, offset, mutatedKeys, new AutoIndexing());
273+
}
274+
275+
@Override
276+
public Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
277+
Query query,
278+
IndexOffset offset,
279+
@Nonnull Set<DocumentKey> mutatedKeys,
280+
AutoIndexing counter) {
253281
return getAll(
254282
Collections.singletonList(query.getPath()),
255283
offset,
256284
Integer.MAX_VALUE,
257-
(MutableDocument doc) -> query.matches(doc) || mutatedKeys.contains(doc.getKey()));
285+
(MutableDocument doc) -> query.matches(doc) || mutatedKeys.contains(doc.getKey()),
286+
counter);
258287
}
259288

260289
private MutableDocument decodeMaybeDocument(

firebase-firestore/src/test/java/com/google/firebase/firestore/local/CountingQueryEngine.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.firebase.firestore.local;
1616

17+
import androidx.annotation.NonNull;
1718
import androidx.annotation.Nullable;
1819
import com.google.firebase.database.collection.ImmutableSortedMap;
1920
import com.google.firebase.database.collection.ImmutableSortedSet;
@@ -152,6 +153,12 @@ public MutableDocument get(DocumentKey documentKey) {
152153

153154
@Override
154155
public Map<DocumentKey, MutableDocument> getAll(Iterable<DocumentKey> documentKeys) {
156+
return getAll(documentKeys, new AutoIndexing());
157+
}
158+
159+
@Override
160+
public Map<DocumentKey, MutableDocument> getAll(
161+
Iterable<DocumentKey> documentKeys, AutoIndexing counter) {
155162
Map<DocumentKey, MutableDocument> result = subject.getAll(documentKeys);
156163
for (MutableDocument document : result.values()) {
157164
documentsReadByKey[0] += document.isValidDocument() ? 1 : 0;
@@ -170,6 +177,15 @@ public Map<DocumentKey, MutableDocument> getAll(
170177
@Override
171178
public Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
172179
Query query, IndexOffset offset, Set<DocumentKey> mutatedKeys) {
180+
return getDocumentsMatchingQuery(query, offset, mutatedKeys, new AutoIndexing());
181+
}
182+
183+
@Override
184+
public Map<DocumentKey, MutableDocument> getDocumentsMatchingQuery(
185+
Query query,
186+
IndexOffset offset,
187+
@NonNull Set<DocumentKey> mutatedKeys,
188+
AutoIndexing counter) {
173189
Map<DocumentKey, MutableDocument> result =
174190
subject.getDocumentsMatchingQuery(query, offset, mutatedKeys);
175191
documentsReadByCollection[0] += result.size();

0 commit comments

Comments
 (0)