github.com/filecoin-project/lassie@v0.23.0/pkg/session/session.go (about)

     1  package session
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/filecoin-project/lassie/pkg/types"
     7  	"github.com/ipni/go-libipni/metadata"
     8  	"github.com/libp2p/go-libp2p/core/peer"
     9  	"github.com/multiformats/go-multicodec"
    10  )
    11  
    12  // Session and State both deal with per-storage provider data and usage
    13  // questions. While State is responsible for gathering data of ongoing
    14  // interactions with storage providers and making dynamic decisions based
    15  // on that information, Session extends it and provides harder rules that
    16  // arise from configuration and other static heuristics.
    17  type Session struct {
    18  	State
    19  	config *Config
    20  }
    21  
    22  // NewSession constructs a new Session with the given config and with or
    23  // without ongoing dynamic data collection. When withState is false, no
    24  // dynamic data will be collected and decisions will be made solely based
    25  // on the config.
    26  func NewSession(config *Config, withState bool) *Session {
    27  	if config == nil {
    28  		config = DefaultConfig()
    29  	}
    30  	var state State
    31  	if withState {
    32  		state = NewSessionState(config)
    33  	} else {
    34  		state = nilstate{}
    35  	}
    36  	if config == nil {
    37  		config = &Config{}
    38  	}
    39  	return &Session{state, config}
    40  }
    41  
    42  // GetStorageProviderTimeout returns the per-retrieval timeout from the
    43  // RetrievalTimeout configuration option.
    44  func (session *Session) GetStorageProviderTimeout(storageProviderId peer.ID) time.Duration {
    45  	return session.config.getProviderConfig(storageProviderId).RetrievalTimeout
    46  }
    47  
    48  // FilterIndexerCandidate filters out protocols that are not acceptable for
    49  // the given candidate. It returns a bool indicating whether the candidate
    50  // should be considered at all, and a new candidate with the filtered
    51  // protocols.
    52  func (session *Session) FilterIndexerCandidate(candidate types.RetrievalCandidate) (bool, types.RetrievalCandidate) {
    53  	if !session.isAcceptableCandidate(candidate.MinerPeer.ID) {
    54  		return false, types.RetrievalCandidate{
    55  			MinerPeer: candidate.MinerPeer,
    56  			RootCid:   candidate.RootCid,
    57  			Metadata:  metadata.Default.New(),
    58  		}
    59  	}
    60  
    61  	protocols := candidate.Metadata.Protocols()
    62  	newProtocolMetadata := make([]metadata.Protocol, 0, len(protocols))
    63  	seen := make(map[multicodec.Code]struct{})
    64  	for _, protocol := range protocols {
    65  		if _, ok := seen[protocol]; ok {
    66  			continue
    67  		}
    68  		seen[protocol] = struct{}{}
    69  		if session.isAcceptableCandidateForProtocol(candidate.MinerPeer.ID, protocol) {
    70  			newProtocolMetadata = append(newProtocolMetadata, candidate.Metadata.Get(protocol))
    71  		}
    72  	}
    73  	return len(newProtocolMetadata) != 0, types.RetrievalCandidate{
    74  		MinerPeer: candidate.MinerPeer,
    75  		RootCid:   candidate.RootCid,
    76  		Metadata:  metadata.Default.New(newProtocolMetadata...),
    77  	}
    78  }
    79  
    80  func (session *Session) isAcceptableCandidate(storageProviderId peer.ID) bool {
    81  	// if blacklisted, candidate is not acceptable
    82  	if session.config.ProviderBlockList[storageProviderId] {
    83  		return false
    84  	}
    85  	// if a whitelist exists and the candidate is not on it, candidate is not acceptable
    86  	if len(session.config.ProviderAllowList) > 0 && !session.config.ProviderAllowList[storageProviderId] {
    87  		return false
    88  	}
    89  	return true
    90  }
    91  
    92  func (session *Session) isAcceptableCandidateForProtocol(storageProviderId peer.ID, protocol multicodec.Code) bool {
    93  	if protocol == multicodec.TransportBitswap {
    94  		return true
    95  	}
    96  
    97  	// check if we are currently retrieving from the candidate with its maximum
    98  	// concurrency
    99  	minerConfig := session.config.getProviderConfig(storageProviderId)
   100  	if minerConfig.MaxConcurrentRetrievals > 0 &&
   101  		session.State.GetConcurrency(storageProviderId) >= minerConfig.MaxConcurrentRetrievals {
   102  		return false
   103  	}
   104  
   105  	return true
   106  }