github.com/turingchain2020/turingchain@v1.1.21/system/mempool/cache.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found In the LICENSE file.
     4  
     5  package mempool
     6  
     7  import (
     8  	"github.com/turingchain2020/turingchain/types"
     9  )
    10  
    11  //QueueCache 排队交易处理
    12  type QueueCache interface {
    13  	Exist(hash string) bool
    14  	GetItem(hash string) (*Item, error)
    15  	Push(tx *Item) error
    16  	Remove(hash string) error
    17  	Size() int
    18  	Walk(count int, cb func(tx *Item) bool)
    19  	GetProperFee() int64
    20  	GetCacheBytes() int64
    21  }
    22  
    23  // Item 为Mempool中包装交易的数据结构
    24  type Item struct {
    25  	Value     *types.Transaction
    26  	Priority  int64
    27  	EnterTime int64
    28  }
    29  
    30  //TxCache 管理交易cache 包括账户索引,最后的交易,排队策略缓存
    31  type txCache struct {
    32  	*AccountTxIndex
    33  	*LastTxCache
    34  	qcache   QueueCache
    35  	totalFee int64
    36  	*SHashTxCache
    37  }
    38  
    39  //NewTxCache init accountIndex and last cache
    40  func newCache(maxTxPerAccount int64, sizeLast int64, poolCacheSize int64) *txCache {
    41  	return &txCache{
    42  		AccountTxIndex: NewAccountTxIndex(int(maxTxPerAccount)),
    43  		LastTxCache:    NewLastTxCache(int(sizeLast)),
    44  		SHashTxCache:   NewSHashTxCache(int(poolCacheSize)),
    45  	}
    46  }
    47  
    48  //SetQueueCache set queue cache , 这个接口可以扩展
    49  func (cache *txCache) SetQueueCache(qcache QueueCache) {
    50  	cache.qcache = qcache
    51  }
    52  
    53  //Remove 移除txCache中给定tx
    54  func (cache *txCache) Remove(hash string) {
    55  	item, err := cache.qcache.GetItem(hash)
    56  	if err != nil {
    57  		return
    58  	}
    59  	tx := item.Value
    60  	err = cache.qcache.Remove(hash)
    61  	if err != nil {
    62  		mlog.Error("Remove", "cache Remove err", err)
    63  	}
    64  	cache.AccountTxIndex.Remove(tx)
    65  	cache.LastTxCache.Remove(tx)
    66  	cache.totalFee -= tx.Fee
    67  	cache.SHashTxCache.Remove(tx)
    68  }
    69  
    70  //Exist 是否存在
    71  func (cache *txCache) Exist(hash string) bool {
    72  	if cache.qcache == nil {
    73  		return false
    74  	}
    75  	return cache.qcache.Exist(hash)
    76  }
    77  
    78  //Size cache tx num
    79  func (cache *txCache) Size() int {
    80  	if cache.qcache == nil {
    81  		return 0
    82  	}
    83  	return cache.qcache.Size()
    84  }
    85  
    86  //TotalFee 手续费总和
    87  func (cache *txCache) TotalFee() int64 {
    88  	return cache.totalFee
    89  }
    90  
    91  //Walk iter all txs
    92  func (cache *txCache) Walk(count int, cb func(tx *Item) bool) {
    93  	if cache.qcache == nil {
    94  		return
    95  	}
    96  	cache.qcache.Walk(count, cb)
    97  }
    98  
    99  //RemoveTxs 删除一组交易
   100  func (cache *txCache) RemoveTxs(txs []string) {
   101  	for _, t := range txs {
   102  		cache.Remove(t)
   103  	}
   104  }
   105  
   106  //Push 存入交易到cache 中
   107  func (cache *txCache) Push(tx *types.Transaction) error {
   108  	if !cache.AccountTxIndex.CanPush(tx) {
   109  		return types.ErrManyTx
   110  	}
   111  	item := &Item{Value: tx, Priority: tx.Fee, EnterTime: types.Now().Unix()}
   112  	err := cache.qcache.Push(item)
   113  	if err != nil {
   114  		return err
   115  	}
   116  	err = cache.AccountTxIndex.Push(tx)
   117  	if err != nil {
   118  		return err
   119  	}
   120  	cache.LastTxCache.Push(tx)
   121  	cache.totalFee += tx.Fee
   122  	cache.SHashTxCache.Push(tx)
   123  	return nil
   124  }
   125  
   126  func (cache *txCache) removeExpiredTx(cfg *types.TuringchainConfig, height, blocktime int64) {
   127  	var txs []string
   128  	cache.qcache.Walk(0, func(tx *Item) bool {
   129  		if isExpired(cfg, tx, height, blocktime) {
   130  			txs = append(txs, string(tx.Value.Hash()))
   131  		}
   132  		return true
   133  	})
   134  	if len(txs) > 0 {
   135  		mlog.Info("removeExpiredTx", "height", height, "totalTxs", cache.Size(), "expiredTxs", len(txs))
   136  		cache.RemoveTxs(txs)
   137  	}
   138  }
   139  
   140  //判断交易是否过期
   141  func isExpired(cfg *types.TuringchainConfig, item *Item, height, blockTime int64) bool {
   142  	if types.Now().Unix()-item.EnterTime >= mempoolExpiredInterval {
   143  		return true
   144  	}
   145  	if item.Value.IsExpire(cfg, height, blockTime) {
   146  		return true
   147  	}
   148  	return false
   149  }
   150  
   151  //getTxByHash 通过交易hash获取tx交易信息
   152  func (cache *txCache) getTxByHash(hash string) *types.Transaction {
   153  	item, err := cache.qcache.GetItem(hash)
   154  	if err != nil {
   155  		return nil
   156  	}
   157  	return item.Value
   158  }