github.com/Ethersocial/go-esn@v0.3.7/swarm/network/stream/peer.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser 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 // The go-ethereum library 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 Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package stream 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "sync" 24 "time" 25 26 "github.com/ethersocial/go-esn/metrics" 27 "github.com/ethersocial/go-esn/p2p/protocols" 28 "github.com/ethersocial/go-esn/swarm/log" 29 pq "github.com/ethersocial/go-esn/swarm/network/priorityqueue" 30 "github.com/ethersocial/go-esn/swarm/network/stream/intervals" 31 "github.com/ethersocial/go-esn/swarm/spancontext" 32 "github.com/ethersocial/go-esn/swarm/state" 33 "github.com/ethersocial/go-esn/swarm/storage" 34 opentracing "github.com/opentracing/opentracing-go" 35 ) 36 37 type notFoundError struct { 38 t string 39 s Stream 40 } 41 42 func newNotFoundError(t string, s Stream) *notFoundError { 43 return ¬FoundError{t: t, s: s} 44 } 45 46 func (e *notFoundError) Error() string { 47 return fmt.Sprintf("%s not found for stream %q", e.t, e.s) 48 } 49 50 // ErrMaxPeerServers will be returned if peer server limit is reached. 51 // It will be sent in the SubscribeErrorMsg. 52 var ErrMaxPeerServers = errors.New("max peer servers") 53 54 // Peer is the Peer extension for the streaming protocol 55 type Peer struct { 56 *protocols.Peer 57 streamer *Registry 58 pq *pq.PriorityQueue 59 serverMu sync.RWMutex 60 clientMu sync.RWMutex // protects both clients and clientParams 61 servers map[Stream]*server 62 clients map[Stream]*client 63 // clientParams map keeps required client arguments 64 // that are set on Registry.Subscribe and used 65 // on creating a new client in offered hashes handler. 66 clientParams map[Stream]*clientParams 67 quit chan struct{} 68 } 69 70 type WrappedPriorityMsg struct { 71 Context context.Context 72 Msg interface{} 73 } 74 75 // NewPeer is the constructor for Peer 76 func NewPeer(peer *protocols.Peer, streamer *Registry) *Peer { 77 p := &Peer{ 78 Peer: peer, 79 pq: pq.New(int(PriorityQueue), PriorityQueueCap), 80 streamer: streamer, 81 servers: make(map[Stream]*server), 82 clients: make(map[Stream]*client), 83 clientParams: make(map[Stream]*clientParams), 84 quit: make(chan struct{}), 85 } 86 ctx, cancel := context.WithCancel(context.Background()) 87 go p.pq.Run(ctx, func(i interface{}) { 88 wmsg := i.(WrappedPriorityMsg) 89 err := p.Send(wmsg.Context, wmsg.Msg) 90 if err != nil { 91 log.Error("Message send error, dropping peer", "peer", p.ID(), "err", err) 92 p.Drop(err) 93 } 94 }) 95 96 // basic monitoring for pq contention 97 go func(pq *pq.PriorityQueue) { 98 ticker := time.NewTicker(5 * time.Second) 99 defer ticker.Stop() 100 for { 101 select { 102 case <-ticker.C: 103 var len_maxi int 104 var cap_maxi int 105 for k := range pq.Queues { 106 if len_maxi < len(pq.Queues[k]) { 107 len_maxi = len(pq.Queues[k]) 108 } 109 110 if cap_maxi < cap(pq.Queues[k]) { 111 cap_maxi = cap(pq.Queues[k]) 112 } 113 } 114 115 metrics.GetOrRegisterGauge(fmt.Sprintf("pq_len_%s", p.ID().TerminalString()), nil).Update(int64(len_maxi)) 116 metrics.GetOrRegisterGauge(fmt.Sprintf("pq_cap_%s", p.ID().TerminalString()), nil).Update(int64(cap_maxi)) 117 case <-p.quit: 118 return 119 } 120 } 121 }(p.pq) 122 123 go func() { 124 <-p.quit 125 cancel() 126 }() 127 return p 128 } 129 130 // Deliver sends a storeRequestMsg protocol message to the peer 131 func (p *Peer) Deliver(ctx context.Context, chunk storage.Chunk, priority uint8) error { 132 var sp opentracing.Span 133 ctx, sp = spancontext.StartSpan( 134 ctx, 135 "send.chunk.delivery") 136 defer sp.Finish() 137 138 msg := &ChunkDeliveryMsg{ 139 Addr: chunk.Address(), 140 SData: chunk.Data(), 141 } 142 return p.SendPriority(ctx, msg, priority) 143 } 144 145 // SendPriority sends message to the peer using the outgoing priority queue 146 func (p *Peer) SendPriority(ctx context.Context, msg interface{}, priority uint8) error { 147 defer metrics.GetOrRegisterResettingTimer(fmt.Sprintf("peer.sendpriority_t.%d", priority), nil).UpdateSince(time.Now()) 148 metrics.GetOrRegisterCounter(fmt.Sprintf("peer.sendpriority.%d", priority), nil).Inc(1) 149 wmsg := WrappedPriorityMsg{ 150 Context: ctx, 151 Msg: msg, 152 } 153 err := p.pq.Push(wmsg, int(priority)) 154 if err == pq.ErrContention { 155 log.Warn("dropping peer on priority queue contention", "peer", p.ID()) 156 p.Drop(err) 157 } 158 return err 159 } 160 161 // SendOfferedHashes sends OfferedHashesMsg protocol msg 162 func (p *Peer) SendOfferedHashes(s *server, f, t uint64) error { 163 var sp opentracing.Span 164 ctx, sp := spancontext.StartSpan( 165 context.TODO(), 166 "send.offered.hashes") 167 defer sp.Finish() 168 169 hashes, from, to, proof, err := s.SetNextBatch(f, t) 170 if err != nil { 171 return err 172 } 173 // true only when quitting 174 if len(hashes) == 0 { 175 return nil 176 } 177 if proof == nil { 178 proof = &HandoverProof{ 179 Handover: &Handover{}, 180 } 181 } 182 s.currentBatch = hashes 183 msg := &OfferedHashesMsg{ 184 HandoverProof: proof, 185 Hashes: hashes, 186 From: from, 187 To: to, 188 Stream: s.stream, 189 } 190 log.Trace("Swarm syncer offer batch", "peer", p.ID(), "stream", s.stream, "len", len(hashes), "from", from, "to", to) 191 return p.SendPriority(ctx, msg, s.priority) 192 } 193 194 func (p *Peer) getServer(s Stream) (*server, error) { 195 p.serverMu.RLock() 196 defer p.serverMu.RUnlock() 197 198 server := p.servers[s] 199 if server == nil { 200 return nil, newNotFoundError("server", s) 201 } 202 return server, nil 203 } 204 205 func (p *Peer) setServer(s Stream, o Server, priority uint8) (*server, error) { 206 p.serverMu.Lock() 207 defer p.serverMu.Unlock() 208 209 if p.servers[s] != nil { 210 return nil, fmt.Errorf("server %s already registered", s) 211 } 212 213 if p.streamer.maxPeerServers > 0 && len(p.servers) >= p.streamer.maxPeerServers { 214 return nil, ErrMaxPeerServers 215 } 216 217 os := &server{ 218 Server: o, 219 stream: s, 220 priority: priority, 221 } 222 p.servers[s] = os 223 return os, nil 224 } 225 226 func (p *Peer) removeServer(s Stream) error { 227 p.serverMu.Lock() 228 defer p.serverMu.Unlock() 229 230 server, ok := p.servers[s] 231 if !ok { 232 return newNotFoundError("server", s) 233 } 234 server.Close() 235 delete(p.servers, s) 236 return nil 237 } 238 239 func (p *Peer) getClient(ctx context.Context, s Stream) (c *client, err error) { 240 var params *clientParams 241 func() { 242 p.clientMu.RLock() 243 defer p.clientMu.RUnlock() 244 245 c = p.clients[s] 246 if c != nil { 247 return 248 } 249 params = p.clientParams[s] 250 }() 251 if c != nil { 252 return c, nil 253 } 254 255 if params != nil { 256 //debug.PrintStack() 257 if err := params.waitClient(ctx); err != nil { 258 return nil, err 259 } 260 } 261 262 p.clientMu.RLock() 263 defer p.clientMu.RUnlock() 264 265 c = p.clients[s] 266 if c != nil { 267 return c, nil 268 } 269 return nil, newNotFoundError("client", s) 270 } 271 272 func (p *Peer) getOrSetClient(s Stream, from, to uint64) (c *client, created bool, err error) { 273 p.clientMu.Lock() 274 defer p.clientMu.Unlock() 275 276 c = p.clients[s] 277 if c != nil { 278 return c, false, nil 279 } 280 281 f, err := p.streamer.GetClientFunc(s.Name) 282 if err != nil { 283 return nil, false, err 284 } 285 286 is, err := f(p, s.Key, s.Live) 287 if err != nil { 288 return nil, false, err 289 } 290 291 cp, err := p.getClientParams(s) 292 if err != nil { 293 return nil, false, err 294 } 295 defer func() { 296 if err == nil { 297 if err := p.removeClientParams(s); err != nil { 298 log.Error("stream set client: remove client params", "stream", s, "peer", p, "err", err) 299 } 300 } 301 }() 302 303 intervalsKey := peerStreamIntervalsKey(p, s) 304 if s.Live { 305 // try to find previous history and live intervals and merge live into history 306 historyKey := peerStreamIntervalsKey(p, NewStream(s.Name, s.Key, false)) 307 historyIntervals := &intervals.Intervals{} 308 err := p.streamer.intervalsStore.Get(historyKey, historyIntervals) 309 switch err { 310 case nil: 311 liveIntervals := &intervals.Intervals{} 312 err := p.streamer.intervalsStore.Get(intervalsKey, liveIntervals) 313 switch err { 314 case nil: 315 historyIntervals.Merge(liveIntervals) 316 if err := p.streamer.intervalsStore.Put(historyKey, historyIntervals); err != nil { 317 log.Error("stream set client: put history intervals", "stream", s, "peer", p, "err", err) 318 } 319 case state.ErrNotFound: 320 default: 321 log.Error("stream set client: get live intervals", "stream", s, "peer", p, "err", err) 322 } 323 case state.ErrNotFound: 324 default: 325 log.Error("stream set client: get history intervals", "stream", s, "peer", p, "err", err) 326 } 327 } 328 329 if err := p.streamer.intervalsStore.Put(intervalsKey, intervals.NewIntervals(from)); err != nil { 330 return nil, false, err 331 } 332 333 next := make(chan error, 1) 334 c = &client{ 335 Client: is, 336 stream: s, 337 priority: cp.priority, 338 to: cp.to, 339 next: next, 340 quit: make(chan struct{}), 341 intervalsStore: p.streamer.intervalsStore, 342 intervalsKey: intervalsKey, 343 } 344 p.clients[s] = c 345 cp.clientCreated() // unblock all possible getClient calls that are waiting 346 next <- nil // this is to allow wantedKeysMsg before first batch arrives 347 return c, true, nil 348 } 349 350 func (p *Peer) removeClient(s Stream) error { 351 p.clientMu.Lock() 352 defer p.clientMu.Unlock() 353 354 client, ok := p.clients[s] 355 if !ok { 356 return newNotFoundError("client", s) 357 } 358 client.close() 359 delete(p.clients, s) 360 return nil 361 } 362 363 func (p *Peer) setClientParams(s Stream, params *clientParams) error { 364 p.clientMu.Lock() 365 defer p.clientMu.Unlock() 366 367 if p.clients[s] != nil { 368 return fmt.Errorf("client %s already exists", s) 369 } 370 if p.clientParams[s] != nil { 371 return fmt.Errorf("client params %s already set", s) 372 } 373 p.clientParams[s] = params 374 return nil 375 } 376 377 func (p *Peer) getClientParams(s Stream) (*clientParams, error) { 378 params := p.clientParams[s] 379 if params == nil { 380 return nil, fmt.Errorf("client params '%v' not provided to peer %v", s, p.ID()) 381 } 382 return params, nil 383 } 384 385 func (p *Peer) removeClientParams(s Stream) error { 386 _, ok := p.clientParams[s] 387 if !ok { 388 return newNotFoundError("client params", s) 389 } 390 delete(p.clientParams, s) 391 return nil 392 } 393 394 func (p *Peer) close() { 395 for _, s := range p.servers { 396 s.Close() 397 } 398 }