浏览代码

Fix the corrupted merge bug in hibernation mode

Signed-off-by: Vadim Markovtsev <vadim@sourced.tech>
Vadim Markovtsev 6 年之前
父节点
当前提交
017d8be663
共有 5 个文件被更改,包括 55 次插入16 次删除
  1. 0 1
      internal/core/forks.go
  2. 35 8
      internal/core/pipeline.go
  3. 4 3
      internal/rbtree/rbtree.go
  4. 1 0
      internal/rbtree/rbtree_test.go
  5. 15 4
      leaves/burndown.go

+ 0 - 1
internal/core/forks.go

@@ -743,7 +743,6 @@ func insertHibernateBoot(plan []runAction, hibernationDistance int) []runAction
 				Items:  hibernates,
 			})
 		}
-
 	}
 	return newPlan
 }

+ 35 - 8
internal/core/pipeline.go

@@ -679,6 +679,38 @@ func (pipeline *Pipeline) Run(commits []*object.Commit) (map[LeafPipelineItem]in
 	var newestTime int64
 	runTimePerItem := map[string]float64{}
 
+	isMerge := func(index int, commit plumbing.Hash) bool {
+		match := false
+		// look for the same hash backward
+		for i := index - 1; i > 0; i-- {
+			switch plan[i].Action {
+			case runActionHibernate, runActionBoot:
+				continue
+			case runActionCommit:
+				match = plan[i].Commit.Hash == commit
+				fallthrough
+			default:
+				i = 0
+			}
+		}
+		if match {
+			return true
+		}
+		// look for the same hash forward
+		for i := index + 1; i < len(plan); i++ {
+			switch plan[i].Action {
+			case runActionHibernate, runActionBoot:
+				continue
+			case runActionCommit:
+				match = plan[i].Commit.Hash == commit
+				fallthrough
+			default:
+				i = len(plan)
+			}
+		}
+		return match
+	}
+
 	commitIndex := 0
 	for index, step := range plan {
 		onProgress(index+1, progressSteps)
@@ -692,14 +724,9 @@ func (pipeline *Pipeline) Run(commits []*object.Commit) (map[LeafPipelineItem]in
 		switch step.Action {
 		case runActionCommit:
 			state := map[string]interface{}{
-				DependencyCommit: step.Commit,
-				DependencyIndex:  commitIndex,
-				DependencyIsMerge: (index > 0 &&
-					plan[index-1].Action == runActionCommit &&
-					plan[index-1].Commit.Hash == step.Commit.Hash) ||
-					(index < (len(plan)-1) &&
-						plan[index+1].Action == runActionCommit &&
-						plan[index+1].Commit.Hash == step.Commit.Hash),
+				DependencyCommit:  step.Commit,
+				DependencyIndex:   commitIndex,
+				DependencyIsMerge: isMerge(index, step.Commit.Hash),
 			}
 			for _, item := range branches[firstItem] {
 				startTime := time.Now()

+ 4 - 3
internal/rbtree/rbtree.go

@@ -53,13 +53,14 @@ func (allocator Allocator) Used() int {
 }
 
 // Clone copies an existing RBTree allocator.
-func (allocator *Allocator) Clone() *Allocator {
+func (allocator Allocator) Clone() *Allocator {
 	if allocator.storage == nil {
 		panic("cannot clone a hibernated allocator")
 	}
 	newAllocator := &Allocator{
-		storage: make([]node, len(allocator.storage), cap(allocator.storage)),
-		gaps:    map[uint32]bool{},
+		HibernationThreshold: allocator.HibernationThreshold,
+		storage:              make([]node, len(allocator.storage), cap(allocator.storage)),
+		gaps:                 map[uint32]bool{},
 	}
 	copy(newAllocator.storage, allocator.storage)
 	for key, val := range allocator.gaps {

+ 1 - 0
internal/rbtree/rbtree_test.go

@@ -443,6 +443,7 @@ func TestAllocatorHibernateBootThreshold(t *testing.T) {
 	alloc := NewAllocator()
 	alloc.malloc()
 	alloc.HibernationThreshold = 3
+	assert.Equal(t, 3, alloc.Clone().HibernationThreshold)
 	alloc.Hibernate()
 	assert.Equal(t, alloc.hibernatedStorageLen, 0)
 	alloc.Boot()

+ 15 - 4
leaves/burndown.go

@@ -447,8 +447,16 @@ func (analyser *BurndownAnalysis) Hibernate() error {
 			return err
 		}
 		analyser.hibernatedFileName = file.Name()
-		file.Close()
-		analyser.fileAllocator.Serialize(analyser.hibernatedFileName)
+		err = file.Close()
+		if err != nil {
+			analyser.hibernatedFileName = ""
+			return err
+		}
+		err = analyser.fileAllocator.Serialize(analyser.hibernatedFileName)
+		if err != nil {
+			analyser.hibernatedFileName = ""
+			return err
+		}
 	}
 	return nil
 }
@@ -456,8 +464,11 @@ func (analyser *BurndownAnalysis) Hibernate() error {
 // Boot decompresses the bound RBTree memory with the files.
 func (analyser *BurndownAnalysis) Boot() error {
 	if analyser.hibernatedFileName != "" {
-		analyser.fileAllocator.Deserialize(analyser.hibernatedFileName)
-		err := os.Remove(analyser.hibernatedFileName)
+		err := analyser.fileAllocator.Deserialize(analyser.hibernatedFileName)
+		if err != nil {
+			return err
+		}
+		err = os.Remove(analyser.hibernatedFileName)
 		if err != nil {
 			return err
 		}