github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/service/session_pool.go (about) 1 /* 2 * Copyright (C) 2018 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package service 19 20 import ( 21 "sync" 22 23 "github.com/mysteriumnetwork/node/identity" 24 "github.com/mysteriumnetwork/node/session" 25 "github.com/mysteriumnetwork/node/session/event" 26 ) 27 28 // NewSessionPool initiates new session storage 29 func NewSessionPool(publisher publisher) *SessionPool { 30 sm := &SessionPool{ 31 sessions: make(map[session.ID]*Session), 32 lock: sync.Mutex{}, 33 publisher: publisher, 34 } 35 return sm 36 } 37 38 // SessionPool maintains all current sessions in memory 39 type SessionPool struct { 40 sessions map[session.ID]*Session 41 lock sync.Mutex 42 publisher publisher 43 } 44 45 // Add puts given session to storage and publishes a creation event. 46 // Multiple sessions per peerID is possible in case different services are used 47 func (sp *SessionPool) Add(instance *Session) { 48 sp.lock.Lock() 49 defer sp.lock.Unlock() 50 51 sp.sessions[instance.ID] = instance 52 sp.publisher.Publish(event.AppTopicSession, instance.toEvent(event.CreatedStatus)) 53 } 54 55 // GetAll returns all sessions in storage 56 func (sp *SessionPool) GetAll() []*Session { 57 sp.lock.Lock() 58 defer sp.lock.Unlock() 59 60 // we're never gonna have more than 100000 sessions ongoing on a single node - performance here should not be an issue. 61 // see Benchmark_Storage_GetAll 62 sessions := make([]*Session, len(sp.sessions)) 63 64 i := 0 65 for _, value := range sp.sessions { 66 sessions[i] = value 67 i++ 68 } 69 return sessions 70 } 71 72 // Find returns underlying session instance 73 func (sp *SessionPool) Find(id session.ID) (*Session, bool) { 74 sp.lock.Lock() 75 defer sp.lock.Unlock() 76 77 instance, found := sp.sessions[id] 78 return instance, found 79 } 80 81 // FindOpts provides fields to search sessions. 82 type FindOpts struct { 83 Peer *identity.Identity 84 ServiceType string 85 } 86 87 // FindBy returns a session by find options. 88 func (sp *SessionPool) FindBy(opts FindOpts) (*Session, bool) { 89 sp.lock.Lock() 90 defer sp.lock.Unlock() 91 92 for _, session := range sp.sessions { 93 if opts.Peer != nil && *opts.Peer != session.ConsumerID { 94 continue 95 } 96 if opts.ServiceType != "" && opts.ServiceType != session.Proposal.ServiceType { 97 continue 98 } 99 return session, true 100 } 101 return nil, false 102 } 103 104 // Remove removes given session from underlying storage 105 func (sp *SessionPool) Remove(id session.ID) { 106 sp.lock.Lock() 107 defer sp.lock.Unlock() 108 109 if instance, found := sp.sessions[id]; found { 110 delete(sp.sessions, id) 111 go sp.publisher.Publish(event.AppTopicSession, instance.toEvent(event.RemovedStatus)) 112 } 113 } 114 115 // RemoveForService removes all sessions which belong to given service 116 func (sp *SessionPool) RemoveForService(serviceID string) { 117 sessions := sp.GetAll() 118 for _, session := range sessions { 119 if session.ServiceID == serviceID { 120 sp.Remove(session.ID) 121 } 122 } 123 }