mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-22 14:56:44 +00:00

* Rename reachabilityManager.data to dataForInsertion, and use it only during insertions * Make reachabilityData an interface * Fix db serialization of reachability data * Fix reachabilityDataStore * Fix all tests * Cleanup debugging code * Fix insertToFutureCoveringSet * Add comments * Rename to ReachabilityData and MutableReachabilityData
171 lines
6.0 KiB
Go
171 lines
6.0 KiB
Go
package reachabilitydatastore
|
|
|
|
import (
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/kaspanet/kaspad/domain/consensus/database/serialization"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/dbkeys"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/lrucache"
|
|
)
|
|
|
|
var reachabilityDataBucket = dbkeys.MakeBucket([]byte("reachability-data"))
|
|
var reachabilityReindexRootKey = dbkeys.MakeBucket().Key([]byte("reachability-reindex-root"))
|
|
|
|
// reachabilityDataStore represents a store of ReachabilityData
|
|
type reachabilityDataStore struct {
|
|
reachabilityDataStaging map[externalapi.DomainHash]model.ReachabilityData
|
|
reachabilityReindexRootStaging *externalapi.DomainHash
|
|
reachabilityDataCache *lrucache.LRUCache
|
|
reachabilityReindexRootCache *externalapi.DomainHash
|
|
}
|
|
|
|
// New instantiates a new ReachabilityDataStore
|
|
func New(cacheSize int) model.ReachabilityDataStore {
|
|
return &reachabilityDataStore{
|
|
reachabilityDataStaging: make(map[externalapi.DomainHash]model.ReachabilityData),
|
|
reachabilityDataCache: lrucache.New(cacheSize),
|
|
}
|
|
}
|
|
|
|
// StageReachabilityData stages the given reachabilityData for the given blockHash
|
|
func (rds *reachabilityDataStore) StageReachabilityData(blockHash *externalapi.DomainHash,
|
|
reachabilityData model.ReachabilityData) {
|
|
|
|
rds.reachabilityDataStaging[*blockHash] = reachabilityData
|
|
}
|
|
|
|
// StageReachabilityReindexRoot stages the given reachabilityReindexRoot
|
|
func (rds *reachabilityDataStore) StageReachabilityReindexRoot(reachabilityReindexRoot *externalapi.DomainHash) {
|
|
rds.reachabilityReindexRootStaging = reachabilityReindexRoot
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) IsAnythingStaged() bool {
|
|
return len(rds.reachabilityDataStaging) != 0 || rds.reachabilityReindexRootStaging != nil
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) Discard() {
|
|
rds.reachabilityDataStaging = make(map[externalapi.DomainHash]model.ReachabilityData)
|
|
rds.reachabilityReindexRootStaging = nil
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) Commit(dbTx model.DBTransaction) error {
|
|
if rds.reachabilityReindexRootStaging != nil {
|
|
reachabilityReindexRootBytes, err := rds.serializeReachabilityReindexRoot(rds.reachabilityReindexRootStaging)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = dbTx.Put(reachabilityReindexRootKey, reachabilityReindexRootBytes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
rds.reachabilityReindexRootCache = rds.reachabilityReindexRootStaging
|
|
}
|
|
for hash, reachabilityData := range rds.reachabilityDataStaging {
|
|
reachabilityDataBytes, err := rds.serializeReachabilityData(reachabilityData)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = dbTx.Put(rds.reachabilityDataBlockHashAsKey(&hash), reachabilityDataBytes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
rds.reachabilityDataCache.Add(&hash, reachabilityData)
|
|
}
|
|
|
|
rds.Discard()
|
|
return nil
|
|
}
|
|
|
|
// ReachabilityData returns the reachabilityData associated with the given blockHash
|
|
func (rds *reachabilityDataStore) ReachabilityData(dbContext model.DBReader,
|
|
blockHash *externalapi.DomainHash) (model.ReachabilityData, error) {
|
|
|
|
if reachabilityData, ok := rds.reachabilityDataStaging[*blockHash]; ok {
|
|
return reachabilityData, nil
|
|
}
|
|
|
|
if reachabilityData, ok := rds.reachabilityDataCache.Get(blockHash); ok {
|
|
return reachabilityData.(model.ReachabilityData), nil
|
|
}
|
|
|
|
reachabilityDataBytes, err := dbContext.Get(rds.reachabilityDataBlockHashAsKey(blockHash))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reachabilityData, err := rds.deserializeReachabilityData(reachabilityDataBytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rds.reachabilityDataCache.Add(blockHash, reachabilityData)
|
|
return reachabilityData, nil
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) HasReachabilityData(dbContext model.DBReader, blockHash *externalapi.DomainHash) (bool, error) {
|
|
if _, ok := rds.reachabilityDataStaging[*blockHash]; ok {
|
|
return true, nil
|
|
}
|
|
|
|
if rds.reachabilityDataCache.Has(blockHash) {
|
|
return true, nil
|
|
}
|
|
|
|
return dbContext.Has(rds.reachabilityDataBlockHashAsKey(blockHash))
|
|
}
|
|
|
|
// ReachabilityReindexRoot returns the current reachability reindex root
|
|
func (rds *reachabilityDataStore) ReachabilityReindexRoot(dbContext model.DBReader) (*externalapi.DomainHash, error) {
|
|
if rds.reachabilityReindexRootStaging != nil {
|
|
return rds.reachabilityReindexRootStaging, nil
|
|
}
|
|
|
|
if rds.reachabilityReindexRootCache != nil {
|
|
return rds.reachabilityReindexRootCache, nil
|
|
}
|
|
|
|
reachabilityReindexRootBytes, err := dbContext.Get(reachabilityReindexRootKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reachabilityReindexRoot, err := rds.deserializeReachabilityReindexRoot(reachabilityReindexRootBytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rds.reachabilityReindexRootCache = reachabilityReindexRoot
|
|
return reachabilityReindexRoot, nil
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) reachabilityDataBlockHashAsKey(hash *externalapi.DomainHash) model.DBKey {
|
|
return reachabilityDataBucket.Key(hash.ByteSlice())
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) serializeReachabilityData(reachabilityData model.ReachabilityData) ([]byte, error) {
|
|
return proto.Marshal(serialization.ReachablityDataToDBReachablityData(reachabilityData))
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) deserializeReachabilityData(reachabilityDataBytes []byte) (model.ReachabilityData, error) {
|
|
dbReachabilityData := &serialization.DbReachabilityData{}
|
|
err := proto.Unmarshal(reachabilityDataBytes, dbReachabilityData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return serialization.DBReachablityDataToReachablityData(dbReachabilityData)
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) serializeReachabilityReindexRoot(reachabilityReindexRoot *externalapi.DomainHash) ([]byte, error) {
|
|
return proto.Marshal(serialization.DomainHashToDbHash(reachabilityReindexRoot))
|
|
}
|
|
|
|
func (rds *reachabilityDataStore) deserializeReachabilityReindexRoot(reachabilityReindexRootBytes []byte) (*externalapi.DomainHash, error) {
|
|
dbHash := &serialization.DbHash{}
|
|
err := proto.Unmarshal(reachabilityReindexRootBytes, dbHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return serialization.DbHashToDomainHash(dbHash)
|
|
}
|