OSDN Git Service

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