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