@@ -155,6 +155,8 @@ func (c cassVersion) nodeUpDelay() time.Duration {
155155 return 10 * time .Second
156156}
157157
158+ // HostInfo represents a server Host/Node. You can create a HostInfo object with either NewHostInfoFromAddrPort or
159+ // NewTestHostInfoFromRow.
158160type HostInfo struct {
159161 // TODO(zariel): reduce locking maybe, not all values will change, but to ensure
160162 // that we are thread safe use a mutex to access all fields.
@@ -181,9 +183,12 @@ type HostInfo struct {
181183 tokens []string
182184}
183185
184- // NewHostInfo creates HostInfo with provided connectAddress and port.
186+ // NewHostInfoFromAddrPort creates HostInfo with provided connectAddress and port.
185187// It returns an error if addr is invalid.
186- func NewHostInfo (addr net.IP , port int ) (* HostInfo , error ) {
188+ //
189+ // If you're looking for a way to create a HostInfo object with more than just an address and port for
190+ // testing purposes then you can use NewTestHostInfoFromRow
191+ func NewHostInfoFromAddrPort (addr net.IP , port int ) (* HostInfo , error ) {
187192 if ! validIpAddr (addr ) {
188193 return nil , errors .New ("invalid host address" )
189194 }
@@ -251,7 +256,7 @@ func (h *HostInfo) nodeToNodeAddress() net.IP {
251256 return net .IPv4zero
252257}
253258
254- // Returns the address that should be used to connect to the host.
259+ // ConnectAddress Returns the address that should be used to connect to the host.
255260// If you wish to override this, use an AddressTranslator
256261func (h * HostInfo ) ConnectAddress () net.IP {
257262 h .mu .RLock ()
@@ -305,7 +310,7 @@ func (h *HostInfo) HostID() string {
305310 return h .hostId
306311}
307312
308- func (h * HostInfo ) SetHostID (hostID string ) {
313+ func (h * HostInfo ) setHostID (hostID string ) {
309314 h .mu .Lock ()
310315 defer h .mu .Unlock ()
311316 h .hostId = hostID
@@ -492,17 +497,42 @@ func checkSystemSchema(control *controlConn) (bool, error) {
492497 return true , nil
493498}
494499
495- func (s * Session ) newHostInfoFromMap (addr net.IP , port int , row map [string ]interface {}) (* HostInfo , error ) {
496- return s .hostInfoFromMap (row , & HostInfo {connectAddress : addr , port : port })
497- }
498-
499500// Given a map that represents a row from either system.local or system.peers
500501// return as much information as we can in *HostInfo
501- func (s * Session ) hostInfoFromMap (row map [string ]interface {}, host * HostInfo ) (* HostInfo , error ) {
502+ func (s * Session ) newHostInfoFromMap (addr net.IP , port int , row map [string ]interface {}) (* HostInfo , error ) {
503+ return newHostInfoFromRow (s , addr , port , row )
504+ }
505+
506+ // NewTestHostInfoFromRow creates a new HostInfo object from a system.peers or system.local row. The port
507+ // defaults to 9042.
508+ //
509+ // You can create a HostInfo object for testing purposes using this function:
510+ //
511+ // Example usage:
512+ //
513+ // row := map[string]interface{}{
514+ // "broadcast_address": net.ParseIP("10.0.0.1"),
515+ // "listen_address": net.ParseIP("10.0.0.1"),
516+ // "rpc_address": net.ParseIP("10.0.0.1"),
517+ // "peer": net.ParseIP("10.0.0.1"), // system.peers only
518+ // "data_center": "dc1",
519+ // "rack": "rack1",
520+ // "host_id": MustRandomUUID(), // can also use ParseUUID("550e8400-e29b-41d4-a716-446655440000")
521+ // "release_version": "4.0.0",
522+ // "native_port": 9042,
523+ // }
524+ // host, err := NewTestHostInfoFromRow(row)
525+ func NewTestHostInfoFromRow (row map [string ]interface {}) (* HostInfo , error ) {
526+ return newHostInfoFromRow (nil , nil , 9042 , row )
527+ }
528+
529+ func newHostInfoFromRow (s * Session , defaultAddr net.IP , defaultPort int , row map [string ]interface {}) (* HostInfo , error ) {
502530 const assertErrorMsg = "Assertion failed for %s, type was %T"
503531 var ok bool
504532
505- // Default to our connected port if the cluster doesn't have port information
533+ host := & HostInfo {connectAddress : defaultAddr , port : defaultPort }
534+
535+ // Process all fields from the row
506536 for key , value := range row {
507537 switch key {
508538 case "data_center" :
@@ -606,18 +636,34 @@ func (s *Session) hostInfoFromMap(row map[string]interface{}, host *HostInfo) (*
606636 }
607637 host .schemaVersion = schemaVersion .String ()
608638 }
609- // TODO(thrawn01): Add 'port'? once CASSANDRA-7544 is complete
610- // Not sure what the port field will be called until the JIRA issue is complete
611639 }
612640
613- ip , port := s .cfg .translateAddressPort (host .ConnectAddress (), host .port )
614- if ! validIpAddr (ip ) {
615- return nil , fmt .Errorf ("invalid host address (before translation: %v:%v, after translation: %v:%v)" , host .ConnectAddress (), host .port , ip .String (), port )
641+ // Determine the connect address from available addresses
642+ if validIpAddr (host .rpcAddress ) {
643+ host .connectAddress = host .rpcAddress
644+ } else if validIpAddr (host .preferredIP ) {
645+ host .connectAddress = host .preferredIP
646+ } else if validIpAddr (host .broadcastAddress ) {
647+ host .connectAddress = host .broadcastAddress
648+ } else if validIpAddr (host .peer ) {
649+ host .connectAddress = host .peer
616650 }
617- host .connectAddress = ip
618- host .port = port
619651
620- return host , nil
652+ if s != nil && s .cfg .AddressTranslator != nil {
653+ ip , port := s .cfg .translateAddressPort (host .ConnectAddress (), host .port )
654+ if ! validIpAddr (ip ) {
655+ return nil , fmt .Errorf ("invalid host address (before translation: %v:%v, after translation: %v:%v)" , host .ConnectAddress (), host .port , ip .String (), port )
656+ }
657+ host .connectAddress = ip
658+ host .port = port
659+ }
660+
661+ if validIpAddr (host .connectAddress ) {
662+ host .hostname = host .connectAddress .String ()
663+ return host , nil
664+ } else {
665+ return nil , errors .New ("invalid host address" )
666+ }
621667}
622668
623669func (s * Session ) hostInfoFromIter (iter * Iter , connectAddress net.IP , defaultPort int ) (* HostInfo , error ) {
0 commit comments