PutExistingCurrentVersion: - NewDoc: new incoming doc - NewDocHLV: new incoming doc's HLV - ExistingDoc: existing doc in bucket (if present) - RevTreeHistory: list of revID's from the incoming docs history (including docs current rev). - ISGRWrite: if this is true then we will align the new write wi
(ctx context.Context, opts PutDocOptions)
| 1318 | // false and len(RevTreeHistory) > 0 then this means the local version of this doc does not have an HLV so this parameter |
| 1319 | // will be used to check for conflicts. |
| 1320 | func (db *DatabaseCollectionWithUser) PutExistingCurrentVersion(ctx context.Context, opts PutDocOptions) (doc *Document, cv *Version, newRevID string, err error) { |
| 1321 | var matchRev string |
| 1322 | if opts.ExistingDoc != nil { |
| 1323 | doc, unmarshalErr := db.unmarshalDocumentWithXattrs(ctx, opts.NewDoc.ID, opts.ExistingDoc.Body, opts.ExistingDoc.Xattrs, opts.ExistingDoc.Cas, DocUnmarshalRev) |
| 1324 | if unmarshalErr != nil { |
| 1325 | return nil, nil, "", base.HTTPErrorf(http.StatusBadRequest, "Error unmarshaling existing doc") |
| 1326 | } |
| 1327 | matchRev = doc.GetRevTreeID() |
| 1328 | } |
| 1329 | generation, _ := ParseRevID(ctx, matchRev) |
| 1330 | if generation < 0 { |
| 1331 | return nil, nil, "", base.HTTPErrorf(http.StatusBadRequest, "Invalid revision ID") |
| 1332 | } |
| 1333 | generation++ //nolint |
| 1334 | |
| 1335 | docUpdateEvent := ExistingVersion |
| 1336 | allowImport := db.UseXattrs() |
| 1337 | updateRevCache := true |
| 1338 | doc, newRevID, err = db.updateAndReturnDoc(ctx, opts.NewDoc.ID, allowImport, &opts.NewDoc.DocExpiry, nil, docUpdateEvent, opts.ExistingDoc, false, updateRevCache, func(doc *Document) (resultDoc *Document, resultAttachmentData updatedAttachments, createNewRevIDSkipped bool, updatedExpiry *uint32, resultErr error) { |
| 1339 | // (Be careful: this block can be invoked multiple times if there are races!) |
| 1340 | |
| 1341 | var isSgWrite bool |
| 1342 | var crc32Match bool |
| 1343 | |
| 1344 | // Is this doc an sgWrite? |
| 1345 | if doc != nil { |
| 1346 | isSgWrite, crc32Match, _ = doc.IsSGWrite(ctx, nil) |
| 1347 | if crc32Match { |
| 1348 | db.dbStats().Database().Crc32MatchCount.Add(1) |
| 1349 | } |
| 1350 | } |
| 1351 | |
| 1352 | // If the existing doc isn't an SG write, import prior to updating |
| 1353 | if doc != nil && !isSgWrite && db.UseXattrs() { |
| 1354 | err := db.OnDemandImportForWrite(ctx, opts.NewDoc.ID, doc, opts.NewDoc.Deleted) |
| 1355 | if err != nil { |
| 1356 | return nil, nil, false, nil, err |
| 1357 | } |
| 1358 | } |
| 1359 | |
| 1360 | // set up revTreeID for backward compatibility |
| 1361 | var previousRevTreeID string |
| 1362 | var prevGeneration int |
| 1363 | var newGeneration int |
| 1364 | if len(opts.RevTreeHistory) == 0 { |
| 1365 | previousRevTreeID = doc.GetRevTreeID() |
| 1366 | prevGeneration, _ = ParseRevID(ctx, previousRevTreeID) |
| 1367 | newGeneration = prevGeneration + 1 |
| 1368 | } else { |
| 1369 | previousRevTreeID = opts.RevTreeHistory[0] |
| 1370 | prevGeneration, _ = ParseRevID(ctx, previousRevTreeID) |
| 1371 | // if incoming rev tree list is from a legacy pre upgraded doc, we should have new revID generation based |
| 1372 | // off the previous current rev +1. If we have rev tree list filled from ISGR's rev tree property then we |
| 1373 | // should use the current rev of inc |
| 1374 | if !opts.ISGRWrite { |
| 1375 | newGeneration = prevGeneration + 1 |
| 1376 | } else { |
| 1377 | newGeneration = prevGeneration |