From 4c3f89f5bca8d8eace187bc5a4d3b7f0502a4d9c Mon Sep 17 00:00:00 2001 From: Paladz Date: Wed, 19 Jun 2019 20:39:48 +0800 Subject: [PATCH] fix the orphan issue (#193) * fix the orphan issue * add unit test --- protocol/orphan_manage.go | 22 +++++++++++++--- protocol/orphan_manage_test.go | 59 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/protocol/orphan_manage.go b/protocol/orphan_manage.go index e0ed49f1..dc72718f 100644 --- a/protocol/orphan_manage.go +++ b/protocol/orphan_manage.go @@ -11,8 +11,8 @@ import ( ) var ( - orphanBlockTTL = 60 * time.Minute - orphanExpireWorkInterval = 3 * time.Minute + orphanBlockTTL = 3 * time.Minute + orphanExpireWorkInterval = 1 * time.Minute numOrphanBlockLimit = 256 ) @@ -58,8 +58,8 @@ func (o *OrphanManage) Add(block *types.Block) { } if len(o.orphan) >= numOrphanBlockLimit { + o.deleteLRU() log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("the number of orphan blocks exceeds the limit") - return } o.orphan[blockHash] = &orphanBlock{block, time.Now().Add(orphanBlockTTL)} @@ -105,13 +105,27 @@ func (o *OrphanManage) delete(hash *bc.Hash) { } for i, preOrphan := range prevOrphans { - if preOrphan == hash { + if *preOrphan == *hash { o.prevOrphans[block.Block.PreviousBlockHash] = append(prevOrphans[:i], prevOrphans[i+1:]...) return } } } +func (o *OrphanManage) deleteLRU() { + var deleteBlock *orphanBlock + for _, orphan := range o.orphan { + if deleteBlock == nil || orphan.expiration.Before(deleteBlock.expiration) { + deleteBlock = orphan + } + } + + if deleteBlock != nil { + blockHash := deleteBlock.Block.Hash() + o.delete(&blockHash) + } +} + func (o *OrphanManage) orphanExpireWorker() { ticker := time.NewTicker(orphanExpireWorkInterval) for now := range ticker.C { diff --git a/protocol/orphan_manage_test.go b/protocol/orphan_manage_test.go index a14aab20..0434745b 100644 --- a/protocol/orphan_manage_test.go +++ b/protocol/orphan_manage_test.go @@ -32,6 +32,65 @@ func init() { } } +func TestDeleteLRU(t *testing.T) { + now := time.Now() + cases := []struct { + before *OrphanManage + after *OrphanManage + }{ + { + before: &OrphanManage{ + orphan: map[bc.Hash]*orphanBlock{ + blockHashes[0]: &orphanBlock{testBlocks[0], now}, + }, + prevOrphans: map[bc.Hash][]*bc.Hash{ + bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]}, + }, + }, + after: &OrphanManage{ + orphan: map[bc.Hash]*orphanBlock{}, + prevOrphans: map[bc.Hash][]*bc.Hash{}, + }, + }, + { + before: &OrphanManage{ + orphan: map[bc.Hash]*orphanBlock{}, + prevOrphans: map[bc.Hash][]*bc.Hash{}, + }, + after: &OrphanManage{ + orphan: map[bc.Hash]*orphanBlock{}, + prevOrphans: map[bc.Hash][]*bc.Hash{}, + }, + }, + { + before: &OrphanManage{ + orphan: map[bc.Hash]*orphanBlock{ + blockHashes[0]: &orphanBlock{testBlocks[0], now.Add(2)}, + blockHashes[1]: &orphanBlock{testBlocks[1], now.Add(1)}, + }, + prevOrphans: map[bc.Hash][]*bc.Hash{ + bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0], &blockHashes[1]}, + }, + }, + after: &OrphanManage{ + orphan: map[bc.Hash]*orphanBlock{ + blockHashes[0]: &orphanBlock{testBlocks[0], now.Add(2)}, + }, + prevOrphans: map[bc.Hash][]*bc.Hash{ + bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]}, + }, + }, + }, + } + + for i, c := range cases { + c.before.deleteLRU() + if !testutil.DeepEqual(c.before, c.after) { + t.Errorf("case %d: got %v want %v", i, c.before, c.after) + } + } +} + func TestOrphanManageAdd(t *testing.T) { cases := []struct { before *OrphanManage -- 2.11.0