Procházet zdrojové kódy

host_source: correctly get local hostinfo (#932)

The system.local table might not have the address info for the connected
host, if this is the case use the connect address from the control
connection.

Add more checks that the connect address is valid to not end up adding
invalid hosts.
Chris Bannister před 8 roky
rodič
revize
c9b77994a0
2 změnil soubory, kde provedl 36 přidání a 12 odebrání
  1. 29 12
      host_source.go
  2. 7 0
      ring.go

+ 29 - 12
host_source.go

@@ -142,6 +142,11 @@ func (h *HostInfo) setPeer(peer net.IP) *HostInfo {
 	return h
 	return h
 }
 }
 
 
+func (h *HostInfo) invalidConnectAddr() bool {
+	addr := h.ConnectAddress()
+	return addr == nil || addr.IsUnspecified()
+}
+
 // Returns the address that should be used to connect to the host.
 // Returns the address that should be used to connect to the host.
 // If you wish to override this, use an AddressTranslator or
 // If you wish to override this, use an AddressTranslator or
 // use a HostFilter to SetConnectAddress()
 // use a HostFilter to SetConnectAddress()
@@ -472,7 +477,16 @@ func (r *ringDescriber) GetLocalHostInfo() (*HostInfo, error) {
 	if it == nil {
 	if it == nil {
 		return nil, errors.New("Attempted to query 'system.local' on a closed control connection")
 		return nil, errors.New("Attempted to query 'system.local' on a closed control connection")
 	}
 	}
-	return r.extractHostInfo(it)
+	host, err := r.extractHostInfo(it)
+	if err != nil {
+		return nil, err
+	}
+
+	if host.invalidConnectAddr() {
+		host.SetConnectAddress(r.session.control.GetHostInfo().ConnectAddress())
+	}
+
+	return host, nil
 }
 }
 
 
 // Given an ip address and port, return a peer that matched the ip address
 // Given an ip address and port, return a peer that matched the ip address
@@ -550,6 +564,8 @@ func (r *ringDescriber) GetHosts() ([]*HostInfo, string, error) {
 	localHost, err := r.GetLocalHostInfo()
 	localHost, err := r.GetLocalHostInfo()
 	if err != nil {
 	if err != nil {
 		return r.prevHosts, r.prevPartitioner, err
 		return r.prevHosts, r.prevPartitioner, err
+	} else if localHost.invalidConnectAddr() {
+		panic(fmt.Sprintf("unable to get localhost connect address: %v", localHost))
 	}
 	}
 
 
 	// Update our list of hosts by querying the cluster
 	// Update our list of hosts by querying the cluster
@@ -602,13 +618,6 @@ func (r *ringDescriber) GetHostInfo(ip net.IP, port int) (*HostInfo, error) {
 	// If we are asking about the same node our control connection has a connection too
 	// If we are asking about the same node our control connection has a connection too
 	if controlHost.ConnectAddress().Equal(ip) {
 	if controlHost.ConnectAddress().Equal(ip) {
 		host, err = r.GetLocalHostInfo()
 		host, err = r.GetLocalHostInfo()
-
-		// Always respect the provided control node address and disregard the ip address
-		// the cassandra node provides. We do this as we are already connected and have a
-		// known valid ip address. This insulates gocql from client connection issues stemming
-		// from node misconfiguration. For instance when a node is run from a container, by
-		// default the node will report its ip address as 127.0.0.1 which is typically invalid.
-		host.SetConnectAddress(ip)
 	} else {
 	} else {
 		host, err = r.GetPeerHostInfo(ip, port)
 		host, err = r.GetPeerHostInfo(ip, port)
 	}
 	}
@@ -618,12 +627,20 @@ func (r *ringDescriber) GetHostInfo(ip net.IP, port int) (*HostInfo, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	// Apply host filter to the result
-	if r.session.cfg.HostFilter != nil && r.session.cfg.HostFilter.Accept(host) != true {
-		return nil, err
+	if controlHost.ConnectAddress().Equal(ip) {
+		// Always respect the provided control node address and disregard the ip address
+		// the cassandra node provides. We do this as we are already connected and have a
+		// known valid ip address. This insulates gocql from client connection issues stemming
+		// from node misconfiguration. For instance when a node is run from a container, by
+		// default the node will report its ip address as 127.0.0.1 which is typically invalid.
+		host.SetConnectAddress(ip)
+	}
+
+	if host.invalidConnectAddr() {
+		return nil, fmt.Errorf("host ConnectAddress invalid: %v", host)
 	}
 	}
 
 
-	return host, err
+	return host, nil
 }
 }
 
 
 func (r *ringDescriber) refreshRing() error {
 func (r *ringDescriber) refreshRing() error {

+ 7 - 0
ring.go

@@ -1,6 +1,7 @@
 package gocql
 package gocql
 
 
 import (
 import (
+	"fmt"
 	"net"
 	"net"
 	"sync"
 	"sync"
 	"sync/atomic"
 	"sync/atomic"
@@ -53,6 +54,9 @@ func (r *ring) allHosts() []*HostInfo {
 }
 }
 
 
 func (r *ring) addHost(host *HostInfo) bool {
 func (r *ring) addHost(host *HostInfo) bool {
+	if host.invalidConnectAddr() {
+		panic(fmt.Sprintf("invalid host: %v", host))
+	}
 	ip := host.ConnectAddress().String()
 	ip := host.ConnectAddress().String()
 
 
 	r.mu.Lock()
 	r.mu.Lock()
@@ -79,6 +83,9 @@ func (r *ring) addOrUpdate(host *HostInfo) *HostInfo {
 }
 }
 
 
 func (r *ring) addHostIfMissing(host *HostInfo) (*HostInfo, bool) {
 func (r *ring) addHostIfMissing(host *HostInfo) (*HostInfo, bool) {
+	if host.invalidConnectAddr() {
+		panic(fmt.Sprintf("invalid host: %v", host))
+	}
 	ip := host.ConnectAddress().String()
 	ip := host.ConnectAddress().String()
 
 
 	r.mu.Lock()
 	r.mu.Lock()