forked from BytomDAO/bytom
/
orphan_manage.go
90 lines (75 loc) · 2.1 KB
/
orphan_manage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package protocol
import (
"sync"
log "github.com/sirupsen/logrus"
"github.com/bytom/protocol/bc"
"github.com/bytom/protocol/bc/types"
)
// OrphanManage is use to handle all the orphan block
type OrphanManage struct {
//TODO: add orphan cached block limit
orphan map[bc.Hash]*types.Block
prevOrphans map[bc.Hash][]*bc.Hash
mtx sync.RWMutex
}
// NewOrphanManage return a new orphan block
func NewOrphanManage() *OrphanManage {
return &OrphanManage{
orphan: make(map[bc.Hash]*types.Block),
prevOrphans: make(map[bc.Hash][]*bc.Hash),
}
}
// BlockExist check is the block in OrphanManage
func (o *OrphanManage) BlockExist(hash *bc.Hash) bool {
o.mtx.RLock()
_, ok := o.orphan[*hash]
o.mtx.RUnlock()
return ok
}
// Add will add the block to OrphanManage
func (o *OrphanManage) Add(block *types.Block) {
blockHash := block.Hash()
o.mtx.Lock()
defer o.mtx.Unlock()
if _, ok := o.orphan[blockHash]; ok {
return
}
o.orphan[blockHash] = block
o.prevOrphans[block.PreviousBlockHash] = append(o.prevOrphans[block.PreviousBlockHash], &blockHash)
log.WithFields(log.Fields{"hash": blockHash.String(), "height": block.Height}).Info("add block to orphan")
}
// Delete will delete the block from OrphanManage
func (o *OrphanManage) Delete(hash *bc.Hash) {
o.mtx.Lock()
defer o.mtx.Unlock()
block, ok := o.orphan[*hash]
if !ok {
return
}
delete(o.orphan, *hash)
prevOrphans, ok := o.prevOrphans[block.PreviousBlockHash]
if !ok || len(prevOrphans) == 1 {
delete(o.prevOrphans, block.PreviousBlockHash)
return
}
for i, preOrphan := range prevOrphans {
if preOrphan == hash {
o.prevOrphans[block.PreviousBlockHash] = append(prevOrphans[:i], prevOrphans[i+1:]...)
return
}
}
}
// Get return the orphan block by hash
func (o *OrphanManage) Get(hash *bc.Hash) (*types.Block, bool) {
o.mtx.RLock()
block, ok := o.orphan[*hash]
o.mtx.RUnlock()
return block, ok
}
// GetPrevOrphans return the list of child orphans
func (o *OrphanManage) GetPrevOrphans(hash *bc.Hash) ([]*bc.Hash, bool) {
o.mtx.RLock()
prevOrphans, ok := o.prevOrphans[*hash]
o.mtx.RUnlock()
return prevOrphans, ok
}