Fix treebuilder errors

This commit is contained in:
mcrakhman 2022-12-13 13:57:23 +01:00 committed by Mikhail Iudin
parent f2f2be36e9
commit fa733293cb
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0

View File

@ -42,29 +42,44 @@ func (tb *treeBuilder) Reset() {
func (tb *treeBuilder) Build(theirHeads []string, newChanges []*Change) (*Tree, error) {
var proposedHeads []string
tb.cache = make(map[string]*Change)
heads, err := tb.treeStorage.Heads()
if err != nil {
return nil, err
}
tb.cache = make(map[string]*Change)
proposedHeads = append(proposedHeads, heads...)
// TODO: we can actually get this from database
// getting old common snapshot
oldBreakpoint, err := tb.findBreakpoint(heads, true)
if err != nil {
// this should never error out, because otherwise we have broken data
return nil, fmt.Errorf("findBreakpoint error: %v", err)
}
if len(theirHeads) > 0 {
proposedHeads = append(proposedHeads, theirHeads...)
}
for _, ch := range newChanges {
// we don't know what new heads are, so every change can be head
if len(theirHeads) == 0 {
// in this case we don't know what new heads are, so every change can be head
proposedHeads = append(proposedHeads, ch.Id)
}
tb.cache[ch.Id] = ch
}
log.With(zap.Strings("heads", proposedHeads)).Debug("building tree")
breakpoint, err := tb.findBreakpoint(proposedHeads)
// getting common snapshot for new heads
breakpoint, err := tb.findBreakpoint(proposedHeads, false)
if err != nil {
return nil, fmt.Errorf("findBreakpoint error: %v", err)
breakpoint = oldBreakpoint
} else {
breakpoint, err = tb.findCommonForTwoSnapshots(oldBreakpoint, breakpoint)
if err != nil {
breakpoint = oldBreakpoint
}
}
proposedHeads = append(proposedHeads, heads...)
log.With(zap.Strings("heads", proposedHeads)).Debug("building tree")
if err = tb.buildTree(proposedHeads, breakpoint); err != nil {
return nil, fmt.Errorf("buildTree error: %v", err)
}
@ -78,13 +93,12 @@ func (tb *treeBuilder) buildTree(heads []string, breakpoint string) (err error)
return
}
tb.tree.AddFast(ch)
changes, err := tb.dfs(heads, breakpoint)
changes := tb.dfs(heads, breakpoint)
tb.tree.AddFast(changes...)
return
}
func (tb *treeBuilder) dfs(heads []string, breakpoint string) (buf []*Change, err error) {
func (tb *treeBuilder) dfs(heads []string, breakpoint string) []*Change {
// initializing buffers
tb.idStack = tb.idStack[:0]
tb.loadBuffer = tb.loadBuffer[:0]
@ -118,7 +132,7 @@ func (tb *treeBuilder) dfs(heads []string, breakpoint string) (buf []*Change, er
tb.idStack = append(tb.idStack, prev)
}
}
return tb.loadBuffer, nil
return tb.loadBuffer
}
func (tb *treeBuilder) loadChange(id string) (ch *Change, err error) {
@ -143,18 +157,34 @@ func (tb *treeBuilder) loadChange(id string) (ch *Change, err error) {
return ch, nil
}
func (tb *treeBuilder) findBreakpoint(heads []string) (breakpoint string, err error) {
func (tb *treeBuilder) findBreakpoint(heads []string, noError bool) (breakpoint string, err error) {
var (
ch *Change
snapshotIds []string
)
for _, head := range heads {
if ch, err = tb.loadChange(head); err != nil {
if noError {
return
}
log.With(zap.String("head", head), zap.Error(err)).Debug("couldn't find head")
continue
}
shId := ch.SnapshotId
if ch.IsSnapshot {
shId = ch.Id
} else {
_, err = tb.loadChange(shId)
if err != nil {
if noError {
return
}
log.With(zap.String("snapshot id", shId), zap.Error(err)).Debug("couldn't find head's snapshot")
continue
}
}
if slice.FindPos(snapshotIds, shId) == -1 {
snapshotIds = append(snapshotIds, shId)
@ -170,6 +200,7 @@ func (tb *treeBuilder) findCommonSnapshot(snapshotIds []string) (snapshotId stri
return "", fmt.Errorf("snapshots not found")
}
// TODO: use divide and conquer to find the snapshot, then we will have only logN findCommonForTwoSnapshots calls
for len(snapshotIds) > 1 {
l := len(snapshotIds)
shId, e := tb.findCommonForTwoSnapshots(snapshotIds[l-2], snapshotIds[l-1])