Fix treebuilder errors
This commit is contained in:
parent
f2f2be36e9
commit
fa733293cb
@ -42,29 +42,44 @@ func (tb *treeBuilder) Reset() {
|
|||||||
|
|
||||||
func (tb *treeBuilder) Build(theirHeads []string, newChanges []*Change) (*Tree, error) {
|
func (tb *treeBuilder) Build(theirHeads []string, newChanges []*Change) (*Tree, error) {
|
||||||
var proposedHeads []string
|
var proposedHeads []string
|
||||||
|
tb.cache = make(map[string]*Change)
|
||||||
heads, err := tb.treeStorage.Heads()
|
heads, err := tb.treeStorage.Heads()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if len(theirHeads) > 0 {
|
||||||
proposedHeads = append(proposedHeads, theirHeads...)
|
proposedHeads = append(proposedHeads, theirHeads...)
|
||||||
}
|
}
|
||||||
for _, ch := range newChanges {
|
for _, ch := range newChanges {
|
||||||
// we don't know what new heads are, so every change can be head
|
|
||||||
if len(theirHeads) == 0 {
|
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)
|
proposedHeads = append(proposedHeads, ch.Id)
|
||||||
}
|
}
|
||||||
tb.cache[ch.Id] = ch
|
tb.cache[ch.Id] = ch
|
||||||
}
|
}
|
||||||
|
|
||||||
log.With(zap.Strings("heads", proposedHeads)).Debug("building tree")
|
// getting common snapshot for new heads
|
||||||
breakpoint, err := tb.findBreakpoint(proposedHeads)
|
breakpoint, err := tb.findBreakpoint(proposedHeads, false)
|
||||||
if err != nil {
|
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 {
|
if err = tb.buildTree(proposedHeads, breakpoint); err != nil {
|
||||||
return nil, fmt.Errorf("buildTree error: %v", err)
|
return nil, fmt.Errorf("buildTree error: %v", err)
|
||||||
}
|
}
|
||||||
@ -78,13 +93,12 @@ func (tb *treeBuilder) buildTree(heads []string, breakpoint string) (err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
tb.tree.AddFast(ch)
|
tb.tree.AddFast(ch)
|
||||||
changes, err := tb.dfs(heads, breakpoint)
|
changes := tb.dfs(heads, breakpoint)
|
||||||
|
|
||||||
tb.tree.AddFast(changes...)
|
tb.tree.AddFast(changes...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tb *treeBuilder) dfs(heads []string, breakpoint string) (buf []*Change, err error) {
|
func (tb *treeBuilder) dfs(heads []string, breakpoint string) []*Change {
|
||||||
// initializing buffers
|
// initializing buffers
|
||||||
tb.idStack = tb.idStack[:0]
|
tb.idStack = tb.idStack[:0]
|
||||||
tb.loadBuffer = tb.loadBuffer[: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)
|
tb.idStack = append(tb.idStack, prev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tb.loadBuffer, nil
|
return tb.loadBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tb *treeBuilder) loadChange(id string) (ch *Change, err error) {
|
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
|
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 (
|
var (
|
||||||
ch *Change
|
ch *Change
|
||||||
snapshotIds []string
|
snapshotIds []string
|
||||||
)
|
)
|
||||||
for _, head := range heads {
|
for _, head := range heads {
|
||||||
if ch, err = tb.loadChange(head); err != nil {
|
if ch, err = tb.loadChange(head); err != nil {
|
||||||
return
|
if noError {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.With(zap.String("head", head), zap.Error(err)).Debug("couldn't find head")
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
shId := ch.SnapshotId
|
shId := ch.SnapshotId
|
||||||
if ch.IsSnapshot {
|
if ch.IsSnapshot {
|
||||||
shId = ch.Id
|
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 {
|
if slice.FindPos(snapshotIds, shId) == -1 {
|
||||||
snapshotIds = append(snapshotIds, shId)
|
snapshotIds = append(snapshotIds, shId)
|
||||||
@ -170,6 +200,7 @@ func (tb *treeBuilder) findCommonSnapshot(snapshotIds []string) (snapshotId stri
|
|||||||
return "", fmt.Errorf("snapshots not found")
|
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 {
|
for len(snapshotIds) > 1 {
|
||||||
l := len(snapshotIds)
|
l := len(snapshotIds)
|
||||||
shId, e := tb.findCommonForTwoSnapshots(snapshotIds[l-2], snapshotIds[l-1])
|
shId, e := tb.findCommonForTwoSnapshots(snapshotIds[l-2], snapshotIds[l-1])
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user