github.com/okex/exchain@v1.8.0/libs/tendermint/mempool/txqueue.go (about)

     1  package mempool
     2  
     3  import (
     4  	"crypto/sha256"
     5  	"sync"
     6  
     7  	"github.com/okex/exchain/libs/tendermint/libs/clist"
     8  	"github.com/okex/exchain/libs/tendermint/types"
     9  )
    10  
    11  type ITransactionQueue interface {
    12  	Len() int
    13  	Insert(tx *mempoolTx) error
    14  	Remove(element *clist.CElement)
    15  	RemoveByKey(key [sha256.Size]byte) *clist.CElement
    16  	Front() *clist.CElement
    17  	Back() *clist.CElement
    18  	BroadcastFront() *clist.CElement
    19  	BroadcastLen() int
    20  	Load(hash [sha256.Size]byte) (*clist.CElement, bool)
    21  	TxsWaitChan() <-chan struct{}
    22  
    23  	AddressRecorder
    24  }
    25  
    26  type AddressRecorder interface {
    27  	GetAddressList() []string
    28  	GetAddressNonce(address string) (uint64, bool)
    29  	GetAddressTxsCnt(address string) int
    30  	GetAddressTxs(address string, max int) types.Txs
    31  	CleanItems(address string, nonce uint64)
    32  }
    33  
    34  type BaseTxQueue struct {
    35  	txs    *clist.CList // FIFO list
    36  	txsMap sync.Map     //txKey -> CElement
    37  
    38  	*AddressRecord
    39  }
    40  
    41  func NewBaseTxQueue() *BaseTxQueue {
    42  	return &BaseTxQueue{
    43  		txs:           clist.New(),
    44  		AddressRecord: newAddressRecord(nil),
    45  	}
    46  }
    47  
    48  func (q *BaseTxQueue) Len() int {
    49  	return q.txs.Len()
    50  }
    51  
    52  func (q *BaseTxQueue) Insert(tx *mempoolTx) error {
    53  	/*
    54  		1. insert tx list
    55  		2. insert address record
    56  		3. insert tx map
    57  	*/
    58  	ele := q.txs.PushBack(tx)
    59  
    60  	q.AddressRecord.AddItem(ele.Address, ele)
    61  	q.txsMap.Store(txKey(ele.Value.(*mempoolTx).tx), ele)
    62  	return nil
    63  }
    64  
    65  func (q *BaseTxQueue) Remove(element *clist.CElement) {
    66  	q.removeElement(element)
    67  	q.AddressRecord.DeleteItem(element)
    68  }
    69  
    70  func (q *BaseTxQueue) RemoveByKey(key [32]byte) (ele *clist.CElement) {
    71  	ele = q.removeElementByKey(key)
    72  	if ele != nil {
    73  		q.AddressRecord.DeleteItem(ele)
    74  	}
    75  	return
    76  }
    77  
    78  func (q *BaseTxQueue) Front() *clist.CElement {
    79  	return q.txs.Front()
    80  }
    81  
    82  func (q *BaseTxQueue) Back() *clist.CElement {
    83  	return q.txs.Back()
    84  }
    85  
    86  func (q *BaseTxQueue) BroadcastFront() *clist.CElement {
    87  	return q.txs.Front()
    88  }
    89  
    90  func (q *BaseTxQueue) BroadcastLen() int {
    91  	return q.txs.Len()
    92  }
    93  
    94  func (q *BaseTxQueue) TxsWaitChan() <-chan struct{} {
    95  	return q.txs.WaitChan()
    96  }
    97  
    98  func (q *BaseTxQueue) Load(hash [sha256.Size]byte) (*clist.CElement, bool) {
    99  	v, ok := q.txsMap.Load(hash)
   100  	if !ok {
   101  		return nil, false
   102  	}
   103  	return v.(*clist.CElement), true
   104  }
   105  
   106  func (q *BaseTxQueue) removeElement(element *clist.CElement) {
   107  	q.txs.Remove(element)
   108  	element.DetachPrev()
   109  
   110  	tx := element.Value.(*mempoolTx).tx
   111  	txHash := txKey(tx)
   112  	q.txsMap.Delete(txHash)
   113  }
   114  
   115  func (q *BaseTxQueue) removeElementByKey(key [32]byte) *clist.CElement {
   116  	if v, ok := q.txsMap.LoadAndDelete(key); ok {
   117  		element := v.(*clist.CElement)
   118  		q.txs.Remove(element)
   119  		element.DetachPrev()
   120  		return element
   121  	}
   122  	return nil
   123  }
   124  
   125  func (q *BaseTxQueue) CleanItems(address string, nonce uint64) {
   126  	q.AddressRecord.CleanItems(address, nonce, q.removeElement)
   127  }