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

     1  package vecmt
     2  
     3  import (
     4  	"github.com/syndtr/goleveldb/leveldb/opt"
     5  	"github.com/unicornultrafoundation/go-helios/hash"
     6  	"github.com/unicornultrafoundation/go-helios/native/dag"
     7  	"github.com/unicornultrafoundation/go-helios/native/idx"
     8  	"github.com/unicornultrafoundation/go-helios/native/pos"
     9  	"github.com/unicornultrafoundation/go-helios/u2udb"
    10  	"github.com/unicornultrafoundation/go-helios/u2udb/table"
    11  	"github.com/unicornultrafoundation/go-helios/utils/cachescale"
    12  	"github.com/unicornultrafoundation/go-helios/utils/wlru"
    13  	"github.com/unicornultrafoundation/go-helios/vecengine"
    14  	"github.com/unicornultrafoundation/go-helios/vecengine/vecflushable"
    15  	"github.com/unicornultrafoundation/go-helios/vecfc"
    16  )
    17  
    18  // IndexCacheConfig - config for cache sizes of Engine
    19  type IndexCacheConfig struct {
    20  	HighestBeforeTimeSize uint
    21  	DBCache               int
    22  }
    23  
    24  // IndexConfig - Engine config (cache sizes)
    25  type IndexConfig struct {
    26  	Fc     vecfc.IndexConfig
    27  	Caches IndexCacheConfig
    28  }
    29  
    30  // Index is a data to detect forkless-cause condition, calculate median timestamp, detect forks.
    31  type Index struct {
    32  	*vecfc.Index
    33  	Base          *vecfc.Index
    34  	baseCallbacks vecengine.Callbacks
    35  
    36  	crit          func(error)
    37  	validators    *pos.Validators
    38  	validatorIdxs map[idx.ValidatorID]idx.Validator
    39  
    40  	getEvent func(hash.Event) dag.Event
    41  
    42  	vecDb u2udb.Store
    43  	table struct {
    44  		HighestBeforeTime u2udb.Store `table:"T"`
    45  	}
    46  
    47  	cache struct {
    48  		HighestBeforeTime *wlru.Cache
    49  	}
    50  
    51  	cfg IndexConfig
    52  }
    53  
    54  // DefaultConfig returns default index config
    55  func DefaultConfig(scale cachescale.Func) IndexConfig {
    56  	return IndexConfig{
    57  		Fc: vecfc.DefaultConfig(scale),
    58  		Caches: IndexCacheConfig{
    59  			HighestBeforeTimeSize: scale.U(160 * 1024),
    60  			DBCache:               scale.I(10 * opt.MiB),
    61  		},
    62  	}
    63  }
    64  
    65  // LiteConfig returns default index config for tests
    66  func LiteConfig() IndexConfig {
    67  	return IndexConfig{
    68  		Fc: vecfc.LiteConfig(),
    69  		Caches: IndexCacheConfig{
    70  			HighestBeforeTimeSize: 4 * 1024,
    71  		},
    72  	}
    73  }
    74  
    75  // NewIndex creates Index instance.
    76  func NewIndex(crit func(error), config IndexConfig) *Index {
    77  	vi := &Index{
    78  		cfg:  config,
    79  		crit: crit,
    80  	}
    81  	engine := vecengine.NewIndex(crit, vi.GetEngineCallbacks())
    82  
    83  	vi.Base = vecfc.NewIndexWithEngine(crit, config.Fc, engine)
    84  	vi.Index = vi.Base
    85  	vi.baseCallbacks = vi.Base.GetEngineCallbacks()
    86  	vi.initCaches()
    87  
    88  	return vi
    89  }
    90  
    91  func NewIndexWithBase(crit func(error), config IndexConfig, base *vecfc.Index) *Index {
    92  	vi := &Index{
    93  		Index:         base,
    94  		Base:          base,
    95  		baseCallbacks: base.GetEngineCallbacks(),
    96  		cfg:           config,
    97  		crit:          crit,
    98  	}
    99  	vi.initCaches()
   100  
   101  	return vi
   102  }
   103  
   104  func (vi *Index) initCaches() {
   105  	vi.cache.HighestBeforeTime, _ = wlru.New(vi.cfg.Caches.HighestBeforeTimeSize, int(vi.cfg.Caches.HighestBeforeTimeSize))
   106  }
   107  
   108  // Reset resets buffers.
   109  func (vi *Index) Reset(validators *pos.Validators, db u2udb.Store, getEvent func(hash.Event) dag.Event) {
   110  	fdb := vecflushable.Wrap(db, vi.cfg.Caches.DBCache)
   111  	vi.vecDb = fdb
   112  	vi.Base.Reset(validators, fdb, getEvent)
   113  	vi.getEvent = getEvent
   114  	vi.validators = validators
   115  	vi.validatorIdxs = validators.Idxs()
   116  	vi.onDropNotFlushed()
   117  
   118  	table.MigrateTables(&vi.table, vi.vecDb)
   119  }
   120  
   121  func (vi *Index) GetEngineCallbacks() vecengine.Callbacks {
   122  	return vecengine.Callbacks{
   123  		GetHighestBefore: func(event hash.Event) vecengine.HighestBeforeI {
   124  			return vi.GetHighestBefore(event)
   125  		},
   126  		GetLowestAfter: func(event hash.Event) vecengine.LowestAfterI {
   127  			return vi.baseCallbacks.GetLowestAfter(event)
   128  		},
   129  		SetHighestBefore: func(event hash.Event, b vecengine.HighestBeforeI) {
   130  			vi.SetHighestBefore(event, b.(*HighestBefore))
   131  		},
   132  		SetLowestAfter: func(event hash.Event, i vecengine.LowestAfterI) {
   133  			vi.baseCallbacks.SetLowestAfter(event, i)
   134  		},
   135  		NewHighestBefore: func(size idx.Validator) vecengine.HighestBeforeI {
   136  			return NewHighestBefore(size)
   137  		},
   138  		NewLowestAfter: func(size idx.Validator) vecengine.LowestAfterI {
   139  			return vi.baseCallbacks.NewLowestAfter(size)
   140  		},
   141  		OnDropNotFlushed: func() {
   142  			vi.baseCallbacks.OnDropNotFlushed()
   143  			vi.onDropNotFlushed()
   144  		},
   145  	}
   146  }
   147  
   148  func (vi *Index) onDropNotFlushed() {
   149  	vi.cache.HighestBeforeTime.Purge()
   150  }
   151  
   152  // GetMergedHighestBefore returns HighestBefore vector clock without branches, where branches are merged into one
   153  func (vi *Index) GetMergedHighestBefore(id hash.Event) *HighestBefore {
   154  	return vi.Engine.GetMergedHighestBefore(id).(*HighestBefore)
   155  }