github.com/lbryio/lbcd@v0.22.119/claimtrie/node/cache.go (about)

     1  package node
     2  
     3  import (
     4  	"container/list"
     5  
     6  	"github.com/lbryio/lbcd/claimtrie/change"
     7  )
     8  
     9  type cacheLeaf struct {
    10  	node    *Node
    11  	element *list.Element
    12  	changes []change.Change
    13  	height  int32
    14  }
    15  
    16  type Cache struct {
    17  	nodes map[string]*cacheLeaf
    18  	order *list.List
    19  	limit int
    20  }
    21  
    22  func (nc *Cache) insert(name []byte, n *Node, height int32) {
    23  	key := string(name)
    24  
    25  	existing := nc.nodes[key]
    26  	if existing != nil {
    27  		existing.node = n
    28  		existing.height = height
    29  		existing.changes = nil
    30  		nc.order.MoveToFront(existing.element)
    31  		return
    32  	}
    33  
    34  	for nc.order.Len() >= nc.limit {
    35  		// TODO: maybe ensure that we don't remove nodes that have a lot of changes?
    36  		delete(nc.nodes, nc.order.Back().Value.(string))
    37  		nc.order.Remove(nc.order.Back())
    38  	}
    39  
    40  	element := nc.order.PushFront(key)
    41  	nc.nodes[key] = &cacheLeaf{node: n, element: element, height: height}
    42  }
    43  
    44  func (nc *Cache) fetch(name []byte, height int32) (*Node, []change.Change, int32) {
    45  	key := string(name)
    46  
    47  	existing := nc.nodes[key]
    48  	if existing != nil && existing.height <= height {
    49  		nc.order.MoveToFront(existing.element)
    50  		return existing.node, existing.changes, existing.height
    51  	}
    52  	return nil, nil, -1
    53  }
    54  
    55  func (nc *Cache) addChanges(changes []change.Change, height int32) {
    56  	for _, c := range changes {
    57  		key := string(c.Name)
    58  		existing := nc.nodes[key]
    59  		if existing != nil && existing.height <= height {
    60  			existing.changes = append(existing.changes, c)
    61  		}
    62  	}
    63  }
    64  
    65  func (nc *Cache) drop(names [][]byte) {
    66  	for _, name := range names {
    67  		key := string(name)
    68  		existing := nc.nodes[key]
    69  		if existing != nil {
    70  			// we can't roll it backwards because we don't know its previous height value; just toast it
    71  			delete(nc.nodes, key)
    72  			nc.order.Remove(existing.element)
    73  		}
    74  	}
    75  }
    76  
    77  func (nc *Cache) clear() {
    78  	nc.nodes = map[string]*cacheLeaf{}
    79  	nc.order = list.New()
    80  	// we'll let the GC sort out the remains...
    81  }
    82  
    83  func NewCache(limit int) *Cache {
    84  	return &Cache{limit: limit, nodes: map[string]*cacheLeaf{}, order: list.New()}
    85  }