// 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 }
// 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 }