Exemplo n.º 1
0
// Gossip receives gossiped information from a peer node.
// The received delta is combined with the infostore, and this
// node's own gossip is returned to requesting client.
func (s *server) Gossip(args *proto.GossipRequest, reply *proto.GossipResponse) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	addr, err := args.Addr.NetAddr()
	if err != nil {
		return util.Errorf("addr %s could not be converted to net.Addr: %s", args.Addr, err)
	}
	lAddr, err := args.LAddr.NetAddr()
	if err != nil {
		return util.Errorf("local addr %s could not be converted to net.Addr: %s", args.LAddr, err)
	}

	// If there is no more capacity to accept incoming clients, return
	// a random already-being-serviced incoming client as an alternate.
	if !s.incoming.hasAddr(addr) {
		if !s.incoming.hasSpace() {
			reply.Alternate = proto.FromNetAddr(s.incoming.selectRandom())
			return nil
		}
		s.incoming.addAddr(addr)
		// This lookup map allows the incoming client to be removed from
		// the incoming addr set when its connection is closed. See
		// server.serveConn() below.
		s.clientAddrMap[lAddr.String()] = addr
	}

	// Update infostore with gossiped infos.
	if args.Delta != nil {
		delta := &infoStore{}
		if err := gob.NewDecoder(bytes.NewBuffer(args.Delta)).Decode(delta); err != nil {
			return util.Errorf("infostore could not be decoded: %s", err)
		}
		log.V(1).Infof("received delta infostore from client %s: %s", addr, delta)
		s.is.combine(delta)
	}
	// If requested max sequence is not -1, wait for gossip interval to expire.
	if args.MaxSeq != -1 {
		s.ready.Wait()
	}
	// The exit condition for waiting clients.
	if s.closed {
		return util.Errorf("gossip server shutdown")
	}
	// Return reciprocal delta.
	delta := s.is.delta(addr, args.MaxSeq)
	if delta != nil {
		var buf bytes.Buffer
		if err := gob.NewEncoder(&buf).Encode(delta); err != nil {
			log.Fatalf("infostore could not be encoded: %s", err)
		}
		reply.Delta = buf.Bytes()
		log.Infof("gossip: client %s sent %d info(s)", addr, delta.infoCount())
	}
	return nil
}
Exemplo n.º 2
0
// Gossip receives gossiped information from a peer node.
// The received delta is combined with the infostore, and this
// node's own gossip is returned to requesting client.
func (s *server) Gossip(args *proto.GossipRequest, reply *proto.GossipResponse) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	addr, err := args.Addr.NetAddr()
	if err != nil {
		return util.Errorf("addr %s could not be converted to net.Addr: %s", args.Addr, err)
	}
	lAddr, err := args.LAddr.NetAddr()
	if err != nil {
		return util.Errorf("local addr %s could not be converted to net.Addr: %s", args.LAddr, err)
	}

	// If there is no more capacity to accept incoming clients, return
	// a random already-being-serviced incoming client as an alternate.
	if !s.incoming.hasNode(args.NodeID) {
		if !s.incoming.hasSpace() {
			idx := rand.Intn(len(s.lAddrMap))
			count := 0
			for _, cInfo := range s.lAddrMap {
				if count == idx {
					reply.Alternate = cInfo.addr
					return nil
				}
				count++
			}
		}
		s.incoming.addNode(args.NodeID)
		// This lookup map allows the incoming client to be removed from
		// the incoming addr set when its connection is closed. See
		// server.serveConn() below.
		s.lAddrMap[lAddr.String()] = clientInfo{args.NodeID, &args.Addr}
	}

	// Update infostore with gossiped infos.
	if args.Delta != nil {
		delta := &infoStore{}
		if err := gob.NewDecoder(bytes.NewBuffer(args.Delta)).Decode(delta); err != nil {
			return util.Errorf("infostore could not be decoded: %s", err)
		}
		if delta.infoCount() > 0 {
			if log.V(1) {
				log.Infof("gossip: received %s", delta)
			} else {
				log.Infof("gossip: received %d info(s) from %s", delta.infoCount(), addr)
			}
		}
		s.is.combine(delta)
	}
	// The exit condition for waiting clients.
	if s.closed {
		return util.Errorf("gossip server shutdown")
	}
	// If requested max sequence is not -1, wait for gossip interval to expire.
	if args.MaxSeq != -1 {
		s.ready.Wait()
	}
	// Return reciprocal delta.
	delta := s.is.delta(args.NodeID, args.MaxSeq)
	if delta != nil {
		var buf bytes.Buffer
		if err := gob.NewEncoder(&buf).Encode(delta); err != nil {
			log.Fatalf("infostore could not be encoded: %s", err)
		}
		reply.Delta = buf.Bytes()
	}
	return nil
}