github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/store_heads.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 sortedHead []byte 14 15 func (es *epochStore) getCachedHeads() (*concurrent.EventsSet, bool) { 16 cache := es.cache.Heads.Load() 17 if cache != nil { 18 return cache.(*concurrent.EventsSet), true 19 } 20 return nil, false 21 } 22 23 func (es *epochStore) loadHeads() *concurrent.EventsSet { 24 res := make(hash.EventsSet, 100) 25 26 b, err := es.table.Heads.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.WrapEventsSet(res) 32 } 33 for i := 0; i < len(b); i += 32 { 34 res.Add(hash.BytesToEvent(b[i : i+32])) 35 } 36 37 return concurrent.WrapEventsSet(res) 38 } 39 40 func (es *epochStore) GetHeads() *concurrent.EventsSet { 41 cached, ok := es.getCachedHeads() 42 if ok { 43 return cached 44 } 45 heads := es.loadHeads() 46 if heads == nil { 47 heads = &concurrent.EventsSet{} 48 } 49 es.cache.Heads.Store(heads) 50 return heads 51 } 52 53 func (es *epochStore) SetHeads(ids *concurrent.EventsSet) { 54 es.cache.Heads.Store(ids) 55 } 56 57 func (es *epochStore) FlushHeads() { 58 ids, ok := es.getCachedHeads() 59 if !ok { 60 return 61 } 62 63 // sort values for determinism 64 sortedHeads := make([]sortedHead, 0, len(ids.Val)) 65 for id := range ids.Val { 66 sortedHeads = append(sortedHeads, id.Bytes()) 67 } 68 sort.Slice(sortedHeads, func(i, j int) bool { 69 a, b := sortedHeads[i], sortedHeads[j] 70 return bytes.Compare(a, b) < 0 71 }) 72 73 b := make([]byte, 0, len(sortedHeads)*32) 74 for _, head := range sortedHeads { 75 b = append(b, head...) 76 } 77 78 if err := es.table.Heads.Put([]byte{}, b); err != nil { 79 es.Log.Crit("Failed to put key-value", "err", err) 80 } 81 } 82 83 // GetHeadsSlice returns IDs of all the epoch events with no descendants 84 func (s *Store) GetHeadsSlice(epoch idx.Epoch) hash.Events { 85 heads := s.GetHeads(epoch) 86 heads.RLock() 87 defer heads.RUnlock() 88 return heads.Val.Slice() 89 } 90 91 // GetHeads returns set of all the epoch event IDs with no descendants 92 func (s *Store) GetHeads(epoch idx.Epoch) *concurrent.EventsSet { 93 es := s.getEpochStore(epoch) 94 if es == nil { 95 return nil 96 } 97 98 return es.GetHeads() 99 } 100 101 func (s *Store) SetHeads(epoch idx.Epoch, ids *concurrent.EventsSet) { 102 es := s.getEpochStore(epoch) 103 if es == nil { 104 return 105 } 106 107 es.SetHeads(ids) 108 }