OSDN Git Service

add expiration for OrphanManage (#1241)
authorDerek <shanhu5739@gmail.com>
Thu, 9 Aug 2018 02:37:53 +0000 (10:37 +0800)
committerPaladz <yzhu101@uottawa.ca>
Thu, 9 Aug 2018 02:37:53 +0000 (10:37 +0800)
* fix the coinbase generate bug (#1136)

* add expiration for OrphanManage

* change OrphanTx to OrphanBlock

* modify expiration for OrphanManage

* modify expiration for OrphanManage again

* adjust the order

* change OrphanBlock to orphanBlock

* adjust the order

protocol/orphan_manage.go

index 0399ffd..04fa7c1 100644 (file)
@@ -2,6 +2,7 @@ package protocol
 
 import (
        "sync"
+       "time"
 
        log "github.com/sirupsen/logrus"
 
@@ -9,20 +10,32 @@ import (
        "github.com/bytom/protocol/bc/types"
 )
 
+var (
+       orphanBlockTTL           = 60 * time.Minute
+       orphanExpireWorkInterval = 3 * time.Minute
+)
+
+type orphanBlock struct {
+       *types.Block
+       expiration time.Time
+}
+
 // OrphanManage is use to handle all the orphan block
 type OrphanManage struct {
-       //TODO: add orphan cached block limit
-       orphan      map[bc.Hash]*types.Block
+       orphan      map[bc.Hash]*orphanBlock
        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),
+       o := &OrphanManage{
+               orphan:      make(map[bc.Hash]*orphanBlock),
                prevOrphans: make(map[bc.Hash][]*bc.Hash),
        }
+
+       go o.orphanExpireWorker()
+       return o
 }
 
 // BlockExist check is the block in OrphanManage
@@ -43,7 +56,7 @@ func (o *OrphanManage) Add(block *types.Block) {
                return
        }
 
-       o.orphan[blockHash] = block
+       o.orphan[blockHash] = &orphanBlock{block, time.Now().Add(orphanBlockTTL)}
        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")
@@ -53,38 +66,60 @@ func (o *OrphanManage) Add(block *types.Block) {
 func (o *OrphanManage) Delete(hash *bc.Hash) {
        o.mtx.Lock()
        defer o.mtx.Unlock()
+       o.delete(hash)
+}
+
+// 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.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
+}
+
+func (o *OrphanManage) delete(hash *bc.Hash) {
        block, ok := o.orphan[*hash]
        if !ok {
                return
        }
        delete(o.orphan, *hash)
 
-       prevOrphans, ok := o.prevOrphans[block.PreviousBlockHash]
+       prevOrphans, ok := o.prevOrphans[block.Block.PreviousBlockHash]
        if !ok || len(prevOrphans) == 1 {
-               delete(o.prevOrphans, block.PreviousBlockHash)
+               delete(o.prevOrphans, block.Block.PreviousBlockHash)
                return
        }
 
        for i, preOrphan := range prevOrphans {
                if preOrphan == hash {
-                       o.prevOrphans[block.PreviousBlockHash] = append(prevOrphans[:i], prevOrphans[i+1:]...)
+                       o.prevOrphans[block.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
+func (o *OrphanManage) orphanExpireWorker() {
+       ticker := time.NewTicker(orphanExpireWorkInterval)
+       for now := range ticker.C {
+               o.orphanExpire(now)
+       }
+       ticker.Stop()
 }
 
-// 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
+func (o *OrphanManage) orphanExpire(now time.Time) {
+       o.mtx.Lock()
+       defer o.mtx.Unlock()
+       for hash, orphan := range o.orphan {
+               if orphan.expiration.Before(now) {
+                       o.delete(&hash)
+               }
+       }
 }