MCPcopy Create free account
hub / github.com/couchbase/sync_gateway / GetDelta

Method GetDelta

db/crud.go:452–619  ·  view source on GitHub ↗

GetDelta attempts to return the delta between fromRevId and toRevId. If the delta can't be generated, returns nil. Delta generation is synchronized per fromRev via a shared revision cache value lock to avoid multiple clients generating the same delta simultaneously.

(ctx context.Context, docID, fromRev, toRev string)

Source from the content-addressed store, hash-verified

450// GetDelta attempts to return the delta between fromRevId and toRevId. If the delta can't be generated, returns nil.
451// Delta generation is synchronized per fromRev via a shared revision cache value lock to avoid multiple clients generating the same delta simultaneously.
452func (db *DatabaseCollectionWithUser) GetDelta(ctx context.Context, docID, fromRev, toRev string) (delta *RevisionDelta, redactedRev *DocumentRevision, err error) {
453 if docID == "" || fromRev == "" || toRev == "" {
454 return nil, nil, nil
455 }
456
457 var initialFromRevision DocumentRevision
458 var fromRevVrs Version
459 fromRevIsCV := !base.IsRevTreeID(fromRev)
460 if fromRevIsCV {
461 fromRevVrs, err = ParseVersion(fromRev)
462 if err != nil {
463 return nil, nil, err
464 }
465 // It is possible delta source will not be resident in the cache and we may want to lookup to the bucket for a backup revision
466 initialFromRevision, err = db.revisionCache.GetWithCV(ctx, docID, &fromRevVrs, RevCacheIncludeDelta, true)
467 if err != nil {
468 return nil, nil, err
469 }
470 } else {
471 initialFromRevision, err = db.revisionCache.GetWithRev(ctx, docID, fromRev, RevCacheIncludeDelta)
472 if err != nil {
473 return nil, nil, err
474 }
475 }
476
477 // If the fromRevision is a removal cache entry (no body), but the user has access to that removal, then just
478 // return 404 missing to indicate that the body of the revision is no longer available.
479 // Delta can't be generated if we don't have the fromRevision body.
480 if initialFromRevision.Removed {
481 return nil, nil, ErrMissing
482 }
483
484 // If the fromRevision was a tombstone, then return error to tell delta sync to send full body replication.
485 if initialFromRevision.Deleted {
486 return nil, nil, base.ErrDeltaSourceIsTombstone
487 }
488
489 // If delta is found, check whether it is a delta for the toRevID we want.
490 if initialFromRevision.Delta != nil && (initialFromRevision.Delta.ToCV == toRev || initialFromRevision.Delta.ToRevID == toRev) {
491 isAuthorized, redactedBody := db.authorizeUserForChannels(docID, toRev, initialFromRevision.CV, initialFromRevision.Delta.ToChannels, initialFromRevision.Delta.ToDeleted, encodeRevisions(ctx, docID, initialFromRevision.Delta.RevisionHistory))
492 if !isAuthorized {
493 return nil, &redactedBody, nil
494 }
495 db.dbStats().DeltaSync().DeltaCacheHit.Add(1)
496 return initialFromRevision.Delta, nil, nil
497 }
498
499 if initialFromRevision.BodyBytes != nil {
500 // Acquire a delta lock to generate delta (ensuring only one toRev unmarshalling/diff for this fromRev and allow racing clients to share the result)
501 initialFromRevision.RevCacheValueDeltaLock.Lock()
502 defer initialFromRevision.RevCacheValueDeltaLock.Unlock()
503
504 // fromRevisionForDiff is a version of the fromRevision that is guarded by the delta lock that we will use to generate the delta (or check again for a newly cached delta)
505 var fromRevisionForDiff DocumentRevision
506 if fromRevIsCV {
507 fromRevisionForDiff, err = db.revisionCache.GetWithCV(ctx, docID, &fromRevVrs, RevCacheIncludeDelta, true)
508 if err != nil {
509 return nil, nil, err

Calls 15

UnmarshalMethod · 0.95
IsRevTreeIDFunction · 0.92
DiffFunction · 0.92
ParseVersionFunction · 0.85
encodeRevisionsFunction · 0.85
newRevCacheDeltaFunction · 0.85
DeleteAttachmentVersionFunction · 0.85
ToAttachmentStorageMetaFunction · 0.85
DeltaSyncMethod · 0.80
dbStatsMethod · 0.80
GetWithCVMethod · 0.65