use of com.google.firebase.firestore.model.MutableDocument in project firebase-android-sdk by firebase.
the class LocalDocumentsView method recalculateAndSaveOverlays.
private void recalculateAndSaveOverlays(Map<DocumentKey, MutableDocument> docs) {
List<MutationBatch> batches = mutationQueue.getAllMutationBatchesAffectingDocumentKeys(docs.keySet());
Map<DocumentKey, FieldMask> masks = new HashMap<>();
// A reverse lookup map from batch id to the documents within that batch.
TreeMap<Integer, Set<DocumentKey>> documentsByBatchId = new TreeMap<>();
// along the way.
for (MutationBatch batch : batches) {
for (DocumentKey key : batch.getKeys()) {
MutableDocument baseDoc = docs.get(key);
if (baseDoc == null) {
// If this batch has documents not included in passed in `docs`, skip them.
continue;
}
FieldMask mask = masks.containsKey(key) ? masks.get(key) : FieldMask.EMPTY;
mask = batch.applyToLocalView(baseDoc, mask);
masks.put(key, mask);
int batchId = batch.getBatchId();
if (!documentsByBatchId.containsKey(batchId)) {
documentsByBatchId.put(batchId, new HashSet<>());
}
documentsByBatchId.get(batchId).add(key);
}
}
Set<DocumentKey> processed = new HashSet<>();
// Iterate in descending order of batch ids, skip documents that are already saved.
for (Map.Entry<Integer, Set<DocumentKey>> entry : documentsByBatchId.descendingMap().entrySet()) {
Map<DocumentKey, Mutation> overlays = new HashMap<>();
for (DocumentKey key : entry.getValue()) {
if (!processed.contains(key)) {
overlays.put(key, Mutation.calculateOverlayMutation(docs.get(key), masks.get(key)));
processed.add(key);
}
}
documentOverlayCache.saveOverlays(entry.getKey(), overlays);
}
}
use of com.google.firebase.firestore.model.MutableDocument in project firebase-android-sdk by firebase.
the class LocalDocumentsView method getNextDocuments.
/**
* Given a collection group, returns the next documents that follow the provided offset, along
* with an updated batch ID.
*
* <p>The documents returned by this method are ordered by remote version from the provided
* offset. If there are no more remote documents after the provided offset, documents with
* mutations in order of batch id from the offset are returned. Since all documents in a batch are
* returned together, the total number of documents returned can exceed {@code count}.
*
* @param collectionGroup The collection group for the documents.
* @param offset The offset to index into.
* @param count The number of documents to return
* @return A LocalDocumentsResult with the documents that follow the provided offset and the last
* processed batch id.
*/
LocalDocumentsResult getNextDocuments(String collectionGroup, IndexOffset offset, int count) {
Map<DocumentKey, MutableDocument> docs = remoteDocumentCache.getAll(collectionGroup, offset, count);
Map<DocumentKey, Overlay> overlays = count - docs.size() > 0 ? documentOverlayCache.getOverlays(collectionGroup, offset.getLargestBatchId(), count - docs.size()) : Collections.emptyMap();
int largestBatchId = FieldIndex.INITIAL_LARGEST_BATCH_ID;
for (Overlay overlay : overlays.values()) {
if (!docs.containsKey(overlay.getKey())) {
docs.put(overlay.getKey(), getBaseDocument(overlay.getKey(), overlay));
}
// The callsite will use the largest batch ID together with the latest read time to create
// a new index offset. Since we only process batch IDs if all remote documents have been read,
// no overlay will increase the overall read time. This is why we only need to special case
// the batch id.
largestBatchId = Math.max(largestBatchId, overlay.getLargestBatchId());
}
populateOverlays(overlays, docs.keySet());
ImmutableSortedMap<DocumentKey, Document> localDocs = computeViews(docs, overlays, Collections.emptySet());
return new LocalDocumentsResult(largestBatchId, localDocs);
}
use of com.google.firebase.firestore.model.MutableDocument in project firebase-android-sdk by firebase.
the class LocalStore method applyBundledDocuments.
@Override
public ImmutableSortedMap<DocumentKey, Document> applyBundledDocuments(ImmutableSortedMap<DocumentKey, MutableDocument> documents, String bundleId) {
// Allocates a target to hold all document keys from the bundle, such that
// they will not get garbage collected right away.
TargetData umbrellaTargetData = allocateTarget(newUmbrellaTarget(bundleId));
return persistence.runTransaction("Apply bundle documents", () -> {
ImmutableSortedSet<DocumentKey> documentKeys = DocumentKey.emptyKeySet();
Map<DocumentKey, MutableDocument> documentMap = new HashMap<>();
for (Entry<DocumentKey, MutableDocument> entry : documents) {
DocumentKey documentKey = entry.getKey();
MutableDocument document = entry.getValue();
if (document.isFoundDocument()) {
documentKeys = documentKeys.insert(documentKey);
}
documentMap.put(documentKey, document);
}
targetCache.removeMatchingKeysForTargetId(umbrellaTargetData.getTargetId());
targetCache.addMatchingKeys(documentKeys, umbrellaTargetData.getTargetId());
DocumentChangeResult result = populateDocumentChanges(documentMap);
Map<DocumentKey, MutableDocument> changedDocs = result.changedDocuments;
return localDocuments.getLocalViewOfDocuments(changedDocs, result.existenceChangedKeys);
});
}
use of com.google.firebase.firestore.model.MutableDocument in project firebase-android-sdk by firebase.
the class LocalStore method populateDocumentChanges.
/**
* Populates the remote document cache with documents from backend or a bundle. Returns the
* document changes resulting from applying those documents, and also a set of documents whose
* existence state are changed as a result.
*
* <p>Note: this function will use `documentVersions` if it is defined. When it is not defined, it
* resorts to `globalVersion`.
*
* @param documents Documents to be applied.
*/
private DocumentChangeResult populateDocumentChanges(Map<DocumentKey, MutableDocument> documents) {
Map<DocumentKey, MutableDocument> changedDocs = new HashMap<>();
List<DocumentKey> removedDocs = new ArrayList<>();
Set<DocumentKey> conditionChanged = new HashSet<>();
// Each loop iteration only affects its "own" doc, so it's safe to get all the remote
// documents in advance in a single call.
Map<DocumentKey, MutableDocument> existingDocs = remoteDocuments.getAll(documents.keySet());
for (Entry<DocumentKey, MutableDocument> entry : documents.entrySet()) {
DocumentKey key = entry.getKey();
MutableDocument doc = entry.getValue();
MutableDocument existingDoc = existingDocs.get(key);
// Check if see if there is a existence state change for this document.
if (doc.isFoundDocument() != existingDoc.isFoundDocument()) {
conditionChanged.add(key);
}
// never add documents to cache.
if (doc.isNoDocument() && doc.getVersion().equals(SnapshotVersion.NONE)) {
// NoDocuments with SnapshotVersion.NONE are used in manufactured events. We remove
// these documents from cache since we lost access.
removedDocs.add(doc.getKey());
changedDocs.put(key, doc);
} else if (!existingDoc.isValidDocument() || doc.getVersion().compareTo(existingDoc.getVersion()) > 0 || (doc.getVersion().compareTo(existingDoc.getVersion()) == 0 && existingDoc.hasPendingWrites())) {
hardAssert(!SnapshotVersion.NONE.equals(doc.getReadTime()), "Cannot add a document when the remote version is zero");
remoteDocuments.add(doc, doc.getReadTime());
changedDocs.put(key, doc);
} else {
Logger.debug("LocalStore", "Ignoring outdated watch update for %s." + "Current version: %s Watch version: %s", key, existingDoc.getVersion(), doc.getVersion());
}
}
remoteDocuments.removeAll(removedDocs);
return new DocumentChangeResult(changedDocs, conditionChanged);
}
use of com.google.firebase.firestore.model.MutableDocument in project firebase-android-sdk by firebase.
the class LocalStore method applyWriteToRemoteDocuments.
private void applyWriteToRemoteDocuments(MutationBatchResult batchResult) {
MutationBatch batch = batchResult.getBatch();
Set<DocumentKey> docKeys = batch.getKeys();
for (DocumentKey docKey : docKeys) {
MutableDocument doc = remoteDocuments.get(docKey);
SnapshotVersion ackVersion = batchResult.getDocVersions().get(docKey);
hardAssert(ackVersion != null, "docVersions should contain every doc in the write.");
if (doc.getVersion().compareTo(ackVersion) < 0) {
batch.applyToRemoteDocument(doc, batchResult);
if (doc.isValidDocument()) {
remoteDocuments.add(doc, batchResult.getCommitVersion());
}
}
}
mutationQueue.removeMutationBatch(batch);
}
Aggregations