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 }