github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/store_last_events.go (about)

     1  package gossip
     2  
     3  import (
     4  	"bytes"
     5  	"sort"
     6  
     7  	"github.com/unicornultrafoundation/go-helios/hash"
     8  	"github.com/unicornultrafoundation/go-helios/native/idx"
     9  
    10  	"github.com/unicornultrafoundation/go-u2u/utils/concurrent"
    11  )
    12  
    13  type sortedLastEvent []byte
    14  
    15  func (es *epochStore) getCachedLastEvents() (*concurrent.ValidatorEventsSet, bool) {
    16  	cache := es.cache.LastEvents.Load()
    17  	if cache != nil {
    18  		return cache.(*concurrent.ValidatorEventsSet), true
    19  	}
    20  	return nil, false
    21  }
    22  
    23  func (es *epochStore) loadLastEvents() *concurrent.ValidatorEventsSet {
    24  	res := make(map[idx.ValidatorID]hash.Event, 100)
    25  
    26  	b, err := es.table.LastEvents.Get([]byte{})
    27  	if err != nil {
    28  		es.Log.Crit("Failed to get key-value", "err", err)
    29  	}
    30  	if b == nil {
    31  		return concurrent.WrapValidatorEventsSet(res)
    32  	}
    33  	for i := 0; i < len(b); i += 32 + 4 {
    34  		res[idx.BytesToValidatorID(b[i:i+4])] = hash.BytesToEvent(b[i+4 : i+4+32])
    35  	}
    36  
    37  	return concurrent.WrapValidatorEventsSet(res)
    38  }
    39  
    40  func (es *epochStore) GetLastEvents() *concurrent.ValidatorEventsSet {
    41  	cached, ok := es.getCachedLastEvents()
    42  	if ok {
    43  		return cached
    44  	}
    45  	heads := es.loadLastEvents()
    46  	if heads == nil {
    47  		heads = &concurrent.ValidatorEventsSet{}
    48  	}
    49  	es.cache.LastEvents.Store(heads)
    50  	return heads
    51  }
    52  
    53  func (es *epochStore) SetLastEvents(ids *concurrent.ValidatorEventsSet) {
    54  	es.cache.LastEvents.Store(ids)
    55  }
    56  
    57  func (es *epochStore) FlushLastEvents() {
    58  	lasts, ok := es.getCachedLastEvents()
    59  	if !ok {
    60  		return
    61  	}
    62  
    63  	// sort values for determinism
    64  	sortedLastEvents := make([]sortedLastEvent, 0, len(lasts.Val))
    65  	for vid, val := range lasts.Val {
    66  		b := append(vid.Bytes(), val.Bytes()...)
    67  		sortedLastEvents = append(sortedLastEvents, b)
    68  	}
    69  	sort.Slice(sortedLastEvents, func(i, j int) bool {
    70  		a, b := sortedLastEvents[i], sortedLastEvents[j]
    71  		return bytes.Compare(a, b) < 0
    72  	})
    73  
    74  	b := make([]byte, 0, len(sortedLastEvents)*(32+4))
    75  	for _, head := range sortedLastEvents {
    76  		b = append(b, head...)
    77  	}
    78  
    79  	if err := es.table.LastEvents.Put([]byte{}, b); err != nil {
    80  		es.Log.Crit("Failed to put key-value", "err", err)
    81  	}
    82  }
    83  
    84  // GetLastEvents returns latest connected epoch events from each validator
    85  func (s *Store) GetLastEvents(epoch idx.Epoch) *concurrent.ValidatorEventsSet {
    86  	es := s.getEpochStore(epoch)
    87  	if es == nil {
    88  		return nil
    89  	}
    90  
    91  	return es.GetLastEvents()
    92  }
    93  
    94  // GetLastEvent returns latest connected epoch event from specified validator
    95  func (s *Store) GetLastEvent(epoch idx.Epoch, vid idx.ValidatorID) *hash.Event {
    96  	es := s.getEpochStore(epoch)
    97  	if es == nil {
    98  		return nil
    99  	}
   100  
   101  	lasts := s.GetLastEvents(epoch)
   102  	lasts.RLock()
   103  	defer lasts.RUnlock()
   104  	last, ok := lasts.Val[vid]
   105  	if !ok {
   106  		return nil
   107  	}
   108  	return &last
   109  }
   110  
   111  func (s *Store) SetLastEvents(epoch idx.Epoch, ids *concurrent.ValidatorEventsSet) {
   112  	es := s.getEpochStore(epoch)
   113  	if es == nil {
   114  		return
   115  	}
   116  
   117  	es.SetLastEvents(ids)
   118  }