(revid string, loader RevLoaderFunc)
| 416 | } |
| 417 | |
| 418 | func (tree RevTree) getRevisionBody(revid string, loader RevLoaderFunc) ([]byte, bool) { |
| 419 | if revid == "" { |
| 420 | // TODO: CBG-1948 |
| 421 | panic("Illegal empty revision ID") |
| 422 | } |
| 423 | info, found := tree[revid] |
| 424 | if !found { |
| 425 | return nil, false |
| 426 | } |
| 427 | |
| 428 | // If we don't have a Body in memory and there's a BodyKey present, attempt to retrieve using the loader |
| 429 | if info.Body == nil && info.BodyKey != "" { |
| 430 | if info.BodyKey != "" { |
| 431 | var err error |
| 432 | info.Body, err = loader(info.BodyKey) |
| 433 | if err != nil { |
| 434 | return nil, false |
| 435 | } |
| 436 | } |
| 437 | } |
| 438 | |
| 439 | // Handling for data affected by https://github.com/couchbase/sync_gateway/issues/3692 |
| 440 | // In that scenario, the revision history includes an entry that should have been moved to a transient |
| 441 | // backup and removed from the rev tree, and the revtree version was modified to include a leading non-JSON byte. |
| 442 | // We ignore these rev history entries, meaning that callers will see the same view of the data |
| 443 | // as if the transient backup had expired. We are not attempting to repair the rev tree, as reclaiming storage |
| 444 | // is a much lower priority than avoiding write errors, and want to avoid introducing additional conflict scenarios. |
| 445 | // The invalid rev tree bodies will eventually be pruned through normal revision tree pruning. |
| 446 | if len(info.Body) > 0 && nonJSONPrefix(info.Body[0]) == nonJSONPrefixKindRevBody { |
| 447 | return nil, false |
| 448 | } |
| 449 | return info.Body, true |
| 450 | } |
| 451 | |
| 452 | func (tree RevTree) setRevisionBody(revid string, body []byte, bodyKey string, hasAttachments bool) { |
| 453 | if revid == "" { |
no test coverage detected