-
Notifications
You must be signed in to change notification settings - Fork 140
CBG-3689: CheckProposedRev does not unmarshall the entire history #7875
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -37,13 +37,14 @@ const DocumentHistoryMaxEntriesPerChannel = 5 | |||||||
| type DocumentUnmarshalLevel uint8 | ||||||||
|
|
||||||||
| const ( | ||||||||
| DocUnmarshalAll = DocumentUnmarshalLevel(iota) // Unmarshals metadata and body | ||||||||
| DocUnmarshalSync // Unmarshals metadata | ||||||||
| DocUnmarshalNoHistory // Unmarshals metadata excluding revtree history | ||||||||
| DocUnmarshalHistory // Unmarshals revtree history + rev + CAS only | ||||||||
| DocUnmarshalRev // Unmarshals revTreeID + CAS only (no HLV) | ||||||||
| DocUnmarshalCAS // Unmarshals CAS (for import check) only | ||||||||
| DocUnmarshalNone // No unmarshalling (skips import/upgrade check) | ||||||||
| DocUnmarshalAll = DocumentUnmarshalLevel(iota) // Unmarshals metadata and body | ||||||||
| DocUnmarshalSync // Unmarshals metadata | ||||||||
| DocUnmarshalNoHistory // Unmarshals metadata excluding revtree history | ||||||||
| DocUnmarshalHistory // Unmarshals revtree history + rev + CAS only | ||||||||
| DocUnmarshalRev // Unmarshals revTreeID + CAS only (no HLV) | ||||||||
| DocUnmarshalCAS // Unmarshals CAS (for import check) only | ||||||||
| DocUnmarshalNone // No unmarshalling (skips import/upgrade check) | ||||||||
| DocUnmarshalRevAndFlags // Unmarshals revTreeID + CAS and Flags (no HLV) | ||||||||
| ) | ||||||||
|
|
||||||||
| const ( | ||||||||
|
|
@@ -167,6 +168,16 @@ func (sd *SyncData) SetCV(hlv *HybridLogicalVector) { | |||||||
| sd.RevAndVersion.CurrentVersion = string(base.Uint64CASToLittleEndianHex(hlv.Version)) | ||||||||
| } | ||||||||
|
|
||||||||
| // hasFlag returns true if the document has this bit flag | ||||||||
| func (sd *SyncData) hasFlag(flag uint8) bool { | ||||||||
torcolvin marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
| return sd.Flags&flag != 0 | ||||||||
| } | ||||||||
|
|
||||||||
| // IsDeleted returns true if the document metadata indicates it is a tombstone. | ||||||||
| func (sd *SyncData) IsDeleted() bool { | ||||||||
torcolvin marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
| return sd.hasFlag(channels.Deleted) | ||||||||
| } | ||||||||
|
|
||||||||
| // RedactRawGlobalSyncData runs HashRedact on the given global sync data. | ||||||||
| func RedactRawGlobalSyncData(syncData []byte, redactSalt string) ([]byte, error) { | ||||||||
| if redactSalt == "" { | ||||||||
|
|
@@ -306,6 +317,11 @@ type revOnlySyncData struct { | |||||||
| CurrentRev channels.RevAndVersion `json:"rev"` | ||||||||
| } | ||||||||
|
|
||||||||
| type revAndFlagsSyncData struct { | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| revOnlySyncData | ||||||||
| Flags uint8 `json:"flags"` | ||||||||
| } | ||||||||
|
|
||||||||
| type casOnlySyncData struct { | ||||||||
| Cas string `json:"cas"` | ||||||||
| } | ||||||||
|
|
@@ -331,10 +347,6 @@ func (doc *Document) MarshalBodyAndSync() (retBytes []byte, err error) { | |||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| func (doc *Document) IsDeleted() bool { | ||||||||
| return doc.hasFlag(channels.Deleted) | ||||||||
| } | ||||||||
|
|
||||||||
| func (doc *Document) BodyWithSpecialProperties(ctx context.Context) ([]byte, error) { | ||||||||
| bodyBytes, err := doc.BodyBytes(ctx) | ||||||||
| if err != nil { | ||||||||
|
|
@@ -754,10 +766,6 @@ func (doc *Document) IsSGWrite(ctx context.Context, rawBody []byte) (isSGWrite b | |||||||
| return true, true, false | ||||||||
| } | ||||||||
|
|
||||||||
| func (doc *Document) hasFlag(flag uint8) bool { | ||||||||
| return doc.Flags&flag != 0 | ||||||||
| } | ||||||||
|
|
||||||||
| func (doc *Document) setFlag(flag uint8, state bool) { | ||||||||
| if state { | ||||||||
| doc.Flags |= flag | ||||||||
|
|
@@ -1336,6 +1344,23 @@ func (doc *Document) UnmarshalWithXattrs(ctx context.Context, data, syncXattrDat | |||||||
| doc.SyncData = SyncData{} | ||||||||
| } | ||||||||
| doc._rawBody = data | ||||||||
| case DocUnmarshalRevAndFlags: | ||||||||
| // Unmarshal rev, cas and flags from sync metadata | ||||||||
| if syncXattrData != nil { | ||||||||
| var revOnlyMeta revAndFlagsSyncData | ||||||||
| unmarshalErr := base.JSONUnmarshal(syncXattrData, &revOnlyMeta) | ||||||||
| if unmarshalErr != nil { | ||||||||
| return pkgerrors.WithStack(base.RedactErrorf("Failed to UnmarshalWithXattrs() doc with id: %s (DocUnmarshalRevAndFlags). Error: %v", base.UD(doc.ID), unmarshalErr)) | ||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: general go style pkgerrors WithStack was used before go implemented its own error wrapping in go 1.13. Some of Sync Gateway's code base was written before this existed. Preferred way of doing this is to use
Suggested change
|
||||||||
| } | ||||||||
| doc.SyncData = SyncData{ | ||||||||
| RevAndVersion: revOnlyMeta.CurrentRev, | ||||||||
| Cas: revOnlyMeta.Cas, | ||||||||
| Flags: revOnlyMeta.Flags, | ||||||||
| } | ||||||||
| } else { | ||||||||
| doc.SyncData = SyncData{} | ||||||||
| } | ||||||||
| doc._rawBody = data | ||||||||
| } | ||||||||
|
|
||||||||
| // If there's no body, but there is an xattr, set deleted flag and initialize an empty body | ||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
To make this easier to read and debug in the future I think I would do something like name these documents with what they are:
const (
singleRevDoc = "singleRevDoc"
twoRevDoc = "twoRevDoc"
tombstonedDoc = "tombstonedDoc"
)