Esempio n. 1
0
// maybeAddResolver creates and adds a resolver for the specified
// address if one does not already exist. Returns whether a new
// resolver was added. The caller must hold the gossip mutex.
func (g *Gossip) maybeAddResolver(addr util.UnresolvedAddr) bool {
	if _, ok := g.resolverAddrs[addr]; !ok {
		r, err := resolver.NewResolverFromUnresolvedAddr(addr)
		if err != nil {
			log.Warningf("bad address %s: %s", addr, err)
			return false
		}
		g.resolvers = append(g.resolvers, r)
		g.resolverAddrs[addr] = struct{}{}
		return true
	}
	return false
}
Esempio n. 2
0
// updateNodeAddress is a gossip callback which fires with each
// update to the node address. This allows us to compute the
// total size of the gossip network (for determining max peers
// each gossip node is allowed to have), as well as to create
// new resolvers for each encountered host and to write the
// set of gossip node addresses to persistent storage when it
// changes.
func (g *Gossip) updateNodeAddress(_ string, content roachpb.Value) {
	var desc roachpb.NodeDescriptor
	if err := content.GetProto(&desc); err != nil {
		log.Error(err)
		return
	}

	g.mu.Lock()
	defer g.mu.Unlock()

	// Recompute max peers based on size of network and set the max
	// sizes for incoming and outgoing node sets.
	defer func() {
		maxPeers := g.maxPeers(len(g.nodeDescs))
		g.incoming.setMaxSize(maxPeers)
		g.outgoing.setMaxSize(maxPeers)
	}()

	// Skip if the node has already been seen or it's our own address.
	if _, ok := g.nodeDescs[desc.NodeID]; ok || desc.Address == g.is.NodeAddr {
		return
	}
	g.nodeDescs[desc.NodeID] = &desc

	// Add this new node to our list of resolvers so we can keep
	// connecting to gossip if the original resolvers go offline.
	r, err := resolver.NewResolverFromUnresolvedAddr(desc.Address)
	if err != nil {
		log.Warningf("bad address from gossip node %s: %s", desc, err)
		return
	}
	if !g.haveResolver(r) {
		g.resolvers = append(g.resolvers, r)
	}
	// Add new address to bootstrap info and persist if possible.
	if !g.haveBootstrapAddress(desc.Address) {
		g.bootstrapInfo.Addresses = append(g.bootstrapInfo.Addresses, desc.Address)
		if g.storage != nil {
			// TODO(spencer): need to clean up ancient gossip nodes, which
			//   will otherwise stick around in the bootstrap info forever.
			if err := g.storage.WriteBootstrapInfo(&g.bootstrapInfo); err != nil {
				log.Error(err)
			}
		}
	}
}
Esempio n. 3
0
// SetStorage provides an instance of the Storage interface
// for reading and writing gossip bootstrap data from persistent
// storage. This should be invoked as early in the lifecycle of a
// gossip instance as possible, but can be called at any time.
func (g *Gossip) SetStorage(storage Storage) error {
	g.mu.Lock()
	defer g.mu.Unlock()
	g.storage = storage

	// Read the bootstrap info from the persistent store.
	var storedBI BootstrapInfo
	err := storage.ReadBootstrapInfo(&storedBI)
	if err != nil {
		log.Warningf("failed to read gossip bootstrap info: %s", err)
	}

	// Merge the stored bootstrap info addresses with any we've become
	// aware of through the --join bootstrap hosts we've connected to.
	if len(g.bootstrapInfo.Addresses) > 0 {
		existing := map[string]struct{}{}
		makeKey := func(a util.UnresolvedAddr) string { return fmt.Sprintf("%s,%s", a.Network(), a.String()) }
		for _, addr := range g.bootstrapInfo.Addresses {
			existing[makeKey(addr)] = struct{}{}
		}
		for _, addr := range storedBI.Addresses {
			// If the address is new, and isn't our own address, add it.
			if _, ok := existing[makeKey(addr)]; !ok && addr != g.is.NodeAddr {
				g.bootstrapInfo.Addresses = append(g.bootstrapInfo.Addresses, addr)
			}
		}
		// Persist merged addresses.
		if numAddrs := len(g.bootstrapInfo.Addresses); numAddrs > len(storedBI.Addresses) {
			if err := g.storage.WriteBootstrapInfo(&g.bootstrapInfo); err != nil {
				log.Error(err)
			}
		}
	} else {
		g.bootstrapInfo = storedBI
	}

	// Cycle through all persisted bootstrap hosts and add resolvers for
	// any which haven't already been added.
	newResolverFound := false
	for _, addr := range g.bootstrapInfo.Addresses {
		r, err := resolver.NewResolverFromUnresolvedAddr(addr)
		if err != nil {
			log.Warningf("bad node address %s: %s", addr, err)
			continue
		}
		if g.haveResolver(r) {
			continue
		}
		// If we find a new resolver, reset the resolver index so that the
		// next resolver we try is the first of the new resolvers.
		if !newResolverFound {
			newResolverFound = true
			g.resolverIdx = len(g.resolvers) - 1
		}
		g.resolvers = append(g.resolvers, r)
	}

	// If a new resolver was found, immediately signal bootstrap.
	if newResolverFound {
		if log.V(1) {
			log.Infof("found new resolvers from storage; signalling bootstrap")
		}
		g.signalStalled()
	}
	return nil
}