Skip to content
Snippets Groups Projects
Select Git revision
  • 1266bcf878a5a233d580dd3faaae8a1168eb799d
  • without_tipselection default
  • develop protected
  • fix/grafana-local-dashboard
  • wasp
  • fix/dashboard-explorer-freeze
  • master
  • feat/timerqueue
  • test/sync_debug_and_650
  • feat/sync_revamp_inv
  • wip/sync
  • tool/db-recovery
  • portcheck/fix
  • fix/synchronization
  • feat/new-dashboard-analysis
  • feat/refactored-analysis-dashboard
  • feat/new-analysis-dashboard
  • test/demo-prometheus-fpc
  • prometheus_metrics
  • wip/analysis-server
  • merge/fpc-test-value-transfer
  • v0.2.2
  • v0.2.1
  • v0.2.0
  • v0.1.3
  • v0.1.2
  • v0.1.1
  • v0.1.0
28 results

approvers.go

Blame
  • approvers.go 3.91 KiB
    package tangle
    
    import (
    	"github.com/dgraph-io/badger"
    	"github.com/iotaledger/goshimmer/packages/database"
    	"github.com/iotaledger/goshimmer/packages/datastructure"
    	"github.com/iotaledger/goshimmer/packages/errors"
    	"github.com/iotaledger/goshimmer/packages/model/approvers"
    	"github.com/iotaledger/goshimmer/packages/node"
    	"github.com/iotaledger/goshimmer/packages/typeutils"
    	"github.com/iotaledger/iota.go/trinary"
    )
    
    // region global public api ////////////////////////////////////////////////////////////////////////////////////////////
    
    // GetApprovers retrieves approvers from the database.
    func GetApprovers(transactionHash trinary.Trytes, computeIfAbsent ...func(trinary.Trytes) *approvers.Approvers) (result *approvers.Approvers, err errors.IdentifiableError) {
    	if cacheResult := approversCache.ComputeIfAbsent(transactionHash, func() interface{} {
    		if dbApprovers, dbErr := getApproversFromDatabase(transactionHash); dbErr != nil {
    			err = dbErr
    
    			return nil
    		} else if dbApprovers != nil {
    			return dbApprovers
    		} else {
    			if len(computeIfAbsent) >= 1 {
    				return computeIfAbsent[0](transactionHash)
    			}
    
    			return nil
    		}
    	}); cacheResult != nil && cacheResult.(*approvers.Approvers) != nil {
    		result = cacheResult.(*approvers.Approvers)
    	}
    
    	return
    }
    
    func ContainsApprovers(transactionHash trinary.Trytes) (result bool, err errors.IdentifiableError) {
    	if approversCache.Contains(transactionHash) {
    		result = true
    	} else {
    		result, err = databaseContainsApprovers(transactionHash)
    	}
    
    	return
    }
    
    func StoreApprovers(approvers *approvers.Approvers) {
    	approversCache.Set(approvers.GetHash(), approvers)
    }
    
    // region lru cache ////////////////////////////////////////////////////////////////////////////////////////////////////
    
    var approversCache = datastructure.NewLRUCache(APPROVERS_CACHE_SIZE, &datastructure.LRUCacheOptions{
    	EvictionCallback: onEvictApprovers,
    })
    
    func onEvictApprovers(_ interface{}, value interface{}) {
    	if evictedApprovers := value.(*approvers.Approvers); evictedApprovers.GetModified() {
    		go func(evictedApprovers *approvers.Approvers) {
    			if err := storeApproversInDatabase(evictedApprovers); err != nil {
    				panic(err)
    			}
    		}(evictedApprovers)
    	}
    }
    
    const (
    	APPROVERS_CACHE_SIZE = 50000
    )
    
    // endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    // region database /////////////////////////////////////////////////////////////////////////////////////////////////////
    
    var approversDatabase database.Database
    
    func configureApproversDatabase(plugin *node.Plugin) {
    	if db, err := database.Get("approvers"); err != nil {
    		panic(err)
    	} else {
    		approversDatabase = db
    	}
    }
    
    func storeApproversInDatabase(approvers *approvers.Approvers) errors.IdentifiableError {
    	if approvers.GetModified() {
    		if err := approversDatabase.Set(typeutils.StringToBytes(approvers.GetHash()), approvers.Marshal()); err != nil {
    			return ErrDatabaseError.Derive(err, "failed to store approvers")
    		}
    
    		approvers.SetModified(false)
    	}
    
    	return nil
    }
    
    func getApproversFromDatabase(transactionHash trinary.Trytes) (*approvers.Approvers, errors.IdentifiableError) {
    	approversData, err := approversDatabase.Get(typeutils.StringToBytes(transactionHash))
    	if err != nil {
    		if err == badger.ErrKeyNotFound {
    			return nil, nil
    		}
    
    		return nil, ErrDatabaseError.Derive(err, "failed to retrieve approvers")
    	}
    
    	var result approvers.Approvers
    	if err = result.Unmarshal(approversData); err != nil {
    		panic(err)
    	}
    
    	return &result, nil
    }
    
    func databaseContainsApprovers(transactionHash trinary.Trytes) (bool, errors.IdentifiableError) {
    	if contains, err := approversDatabase.Contains(typeutils.StringToBytes(transactionHash)); err != nil {
    		return false, ErrDatabaseError.Derive(err, "failed to check if the approvers exists")
    	} else {
    		return contains, nil
    	}
    }
    
    // endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////