github.com/koko1123/flow-go-1@v0.29.6/module/buffer/backend.go (about)

     1  package buffer
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/koko1123/flow-go-1/model/flow"
     7  )
     8  
     9  // item represents an item in the cache: a block header, payload, and the ID
    10  // of the node that sent it to us. The payload is generic.
    11  type item struct {
    12  	originID flow.Identifier
    13  	header   *flow.Header
    14  	payload  interface{}
    15  }
    16  
    17  // backend implements a simple cache of pending blocks, indexed by parent ID.
    18  type backend struct {
    19  	mu sync.RWMutex
    20  	// map of pending block IDs, keyed by parent ID for ByParentID lookups
    21  	blocksByParent map[flow.Identifier][]flow.Identifier
    22  	// set of pending blocks, keyed by ID to avoid duplication
    23  	blocksByID map[flow.Identifier]*item
    24  }
    25  
    26  // newBackend returns a new pending block cache.
    27  func newBackend() *backend {
    28  	cache := &backend{
    29  		blocksByParent: make(map[flow.Identifier][]flow.Identifier),
    30  		blocksByID:     make(map[flow.Identifier]*item),
    31  	}
    32  	return cache
    33  }
    34  
    35  // add adds the item to the cache, returning false if it already exists and
    36  // true otherwise.
    37  func (b *backend) add(originID flow.Identifier, header *flow.Header, payload interface{}) bool {
    38  
    39  	b.mu.Lock()
    40  	defer b.mu.Unlock()
    41  
    42  	blockID := header.ID()
    43  
    44  	_, exists := b.blocksByID[blockID]
    45  	if exists {
    46  		return false
    47  	}
    48  
    49  	item := &item{
    50  		header:   header,
    51  		originID: originID,
    52  		payload:  payload,
    53  	}
    54  
    55  	b.blocksByID[blockID] = item
    56  	b.blocksByParent[header.ParentID] = append(b.blocksByParent[header.ParentID], blockID)
    57  
    58  	return true
    59  }
    60  
    61  func (b *backend) byID(id flow.Identifier) (*item, bool) {
    62  
    63  	b.mu.RLock()
    64  	defer b.mu.RUnlock()
    65  
    66  	item, exists := b.blocksByID[id]
    67  	if !exists {
    68  		return nil, false
    69  	}
    70  
    71  	return item, true
    72  }
    73  
    74  // byParentID returns a list of cached blocks with the given parent. If no such
    75  // blocks exist, returns false.
    76  func (b *backend) byParentID(parentID flow.Identifier) ([]*item, bool) {
    77  
    78  	b.mu.RLock()
    79  	defer b.mu.RUnlock()
    80  
    81  	forParent, exists := b.blocksByParent[parentID]
    82  	if !exists {
    83  		return nil, false
    84  	}
    85  
    86  	items := make([]*item, 0, len(forParent))
    87  	for _, blockID := range forParent {
    88  		items = append(items, b.blocksByID[blockID])
    89  	}
    90  
    91  	return items, true
    92  }
    93  
    94  // dropForParent removes all cached blocks with the given parent (non-recursively).
    95  func (b *backend) dropForParent(parentID flow.Identifier) {
    96  
    97  	b.mu.Lock()
    98  	defer b.mu.Unlock()
    99  
   100  	children, exists := b.blocksByParent[parentID]
   101  	if !exists {
   102  		return
   103  	}
   104  
   105  	for _, childID := range children {
   106  		delete(b.blocksByID, childID)
   107  	}
   108  	delete(b.blocksByParent, parentID)
   109  }
   110  
   111  // pruneByView prunes any items in the cache that have view less than or
   112  // equal to the given view. The pruning view should be the finalized view.
   113  func (b *backend) pruneByView(view uint64) {
   114  
   115  	b.mu.Lock()
   116  	defer b.mu.Unlock()
   117  
   118  	for id, item := range b.blocksByID {
   119  		if item.header.View <= view {
   120  			delete(b.blocksByID, id)
   121  			delete(b.blocksByParent, item.header.ParentID)
   122  		}
   123  	}
   124  }
   125  
   126  // size returns the number of elements stored in teh backend
   127  func (b *backend) size() uint {
   128  	b.mu.RLock()
   129  	defer b.mu.RUnlock()
   130  	return uint(len(b.blocksByID))
   131  }