@@ -171,6 +171,7 @@ type HostInfo struct {
171
171
port int
172
172
dataCenter string
173
173
rack string
174
+ missingRack bool
174
175
hostId string
175
176
workload string
176
177
graph bool
@@ -413,8 +414,9 @@ func (h *HostInfo) update(from *HostInfo) {
413
414
if h .dataCenter == "" {
414
415
h .dataCenter = from .dataCenter
415
416
}
416
- if h .rack == "" {
417
+ if h .missingRack || h . rack == "" {
417
418
h .rack = from .rack
419
+ h .missingRack = from .missingRack
418
420
}
419
421
if h .hostId == "" {
420
422
h .hostId = from .hostId
@@ -530,7 +532,7 @@ func newHostInfoFromRow(s *Session, defaultAddr net.IP, defaultPort int, row map
530
532
const assertErrorMsg = "Assertion failed for %s, type was %T"
531
533
var ok bool
532
534
533
- host := & HostInfo {connectAddress : defaultAddr , port : defaultPort }
535
+ host := & HostInfo {connectAddress : defaultAddr , port : defaultPort , missingRack : true }
534
536
535
537
// Process all fields from the row
536
538
for key , value := range row {
@@ -541,14 +543,30 @@ func newHostInfoFromRow(s *Session, defaultAddr net.IP, defaultPort int, row map
541
543
return nil , fmt .Errorf (assertErrorMsg , "data_center" , value )
542
544
}
543
545
case "rack" :
544
- host . rack , ok = value .(string )
546
+ rack , ok : = value .(* string )
545
547
if ! ok {
546
- return nil , fmt .Errorf (assertErrorMsg , "rack" , value )
548
+ if rack , ok := value .(string ); ! ok {
549
+ return nil , fmt .Errorf (assertErrorMsg , "rack" , value )
550
+ } else {
551
+ host .rack = rack
552
+ host .missingRack = false
553
+ }
554
+ } else if rack != nil {
555
+ host .rack = * rack
556
+ host .missingRack = false
547
557
}
548
558
case "host_id" :
549
559
hostId , ok := value .(UUID )
550
560
if ! ok {
551
- return nil , fmt .Errorf (assertErrorMsg , "host_id" , value )
561
+ if str , ok := value .(string ); ok {
562
+ var err error
563
+ hostId , err = ParseUUID (str )
564
+ if err != nil {
565
+ return nil , fmt .Errorf ("failed to parse host_id: %w" , err )
566
+ }
567
+ } else {
568
+ return nil , fmt .Errorf (assertErrorMsg , "host_id" , value )
569
+ }
552
570
}
553
571
host .hostId = hostId .String ()
554
572
case "release_version" :
@@ -560,7 +578,11 @@ func newHostInfoFromRow(s *Session, defaultAddr net.IP, defaultPort int, row map
560
578
case "peer" :
561
579
ip , ok := value .(net.IP )
562
580
if ! ok {
563
- return nil , fmt .Errorf (assertErrorMsg , "peer" , value )
581
+ if str , ok := value .(string ); ok {
582
+ ip = net .ParseIP (str )
583
+ } else {
584
+ return nil , fmt .Errorf (assertErrorMsg , "peer" , value )
585
+ }
564
586
}
565
587
host .peer = ip
566
588
case "cluster_name" :
@@ -576,31 +598,51 @@ func newHostInfoFromRow(s *Session, defaultAddr net.IP, defaultPort int, row map
576
598
case "broadcast_address" :
577
599
ip , ok := value .(net.IP )
578
600
if ! ok {
579
- return nil , fmt .Errorf (assertErrorMsg , "broadcast_address" , value )
601
+ if str , ok := value .(string ); ok {
602
+ ip = net .ParseIP (str )
603
+ } else {
604
+ return nil , fmt .Errorf (assertErrorMsg , "broadcast_address" , value )
605
+ }
580
606
}
581
607
host .broadcastAddress = ip
582
608
case "preferred_ip" :
583
609
ip , ok := value .(net.IP )
584
610
if ! ok {
585
- return nil , fmt .Errorf (assertErrorMsg , "preferred_ip" , value )
611
+ if str , ok := value .(string ); ok {
612
+ ip = net .ParseIP (str )
613
+ } else {
614
+ return nil , fmt .Errorf (assertErrorMsg , "preferred_ip" , value )
615
+ }
586
616
}
587
617
host .preferredIP = ip
588
618
case "rpc_address" :
589
619
ip , ok := value .(net.IP )
590
620
if ! ok {
591
- return nil , fmt .Errorf (assertErrorMsg , "rpc_address" , value )
621
+ if str , ok := value .(string ); ok {
622
+ ip = net .ParseIP (str )
623
+ } else {
624
+ return nil , fmt .Errorf (assertErrorMsg , "rpc_address" , value )
625
+ }
592
626
}
593
627
host .rpcAddress = ip
594
628
case "native_address" :
595
629
ip , ok := value .(net.IP )
596
630
if ! ok {
597
- return nil , fmt .Errorf (assertErrorMsg , "native_address" , value )
631
+ if str , ok := value .(string ); ok {
632
+ ip = net .ParseIP (str )
633
+ } else {
634
+ return nil , fmt .Errorf (assertErrorMsg , "native_address" , value )
635
+ }
598
636
}
599
637
host .rpcAddress = ip
600
638
case "listen_address" :
601
639
ip , ok := value .(net.IP )
602
640
if ! ok {
603
- return nil , fmt .Errorf (assertErrorMsg , "listen_address" , value )
641
+ if str , ok := value .(string ); ok {
642
+ ip = net .ParseIP (str )
643
+ } else {
644
+ return nil , fmt .Errorf (assertErrorMsg , "listen_address" , value )
645
+ }
604
646
}
605
647
host .listenAddress = ip
606
648
case "native_port" :
@@ -667,17 +709,22 @@ func newHostInfoFromRow(s *Session, defaultAddr net.IP, defaultPort int, row map
667
709
}
668
710
669
711
func (s * Session ) hostInfoFromIter (iter * Iter , connectAddress net.IP , defaultPort int ) (* HostInfo , error ) {
670
- rows , err := iter .SliceMap ()
671
- if err != nil {
672
- // TODO(zariel): make typed error
673
- return nil , err
712
+ // TODO: switch this to a new iterator method once CASSGO-36 is solved
713
+ m := map [string ]interface {}{
714
+ // we set rack to a pointer so we can know if it's NULL or not since we
715
+ // need to be able to filter out NULL rack hosts but not empty string hosts
716
+ // see CASSGO-6
717
+ "rack" : new (string ),
674
718
}
675
-
676
- if len (rows ) == 0 {
719
+ if ! iter .MapScan (m ) {
677
720
return nil , errors .New ("query returned 0 rows" )
678
721
}
722
+ if err := iter .Close (); err != nil {
723
+ // TODO(zariel): make typed error
724
+ return nil , err
725
+ }
679
726
680
- host , err := s .newHostInfoFromMap (connectAddress , defaultPort , rows [ 0 ] )
727
+ host , err := s .newHostInfoFromMap (connectAddress , defaultPort , m )
681
728
if err != nil {
682
729
return nil , err
683
730
}
@@ -720,8 +767,21 @@ func (r *ringDescriber) getClusterPeerInfo(localHost *HostInfo) ([]*HostInfo, er
720
767
return nil , errNoControl
721
768
}
722
769
723
- rows , err := iter .SliceMap ()
724
- if err != nil {
770
+ // TODO: switch this to a new iterator method once CASSGO-36 is solved
771
+ var rows []map [string ]interface {}
772
+ for {
773
+ m := map [string ]interface {}{
774
+ // we set rack to a pointer so we can know if it's NULL or not since we
775
+ // need to be able to filter out NULL rack hosts but not empty string hosts
776
+ // see CASSGO-6
777
+ "rack" : new (string ),
778
+ }
779
+ if ! iter .MapScan (m ) {
780
+ break
781
+ }
782
+ rows = append (rows , m )
783
+ }
784
+ if err := iter .Close (); err != nil {
725
785
// TODO(zariel): make typed error
726
786
return nil , fmt .Errorf ("unable to fetch peer host info: %s" , err )
727
787
}
@@ -749,7 +809,7 @@ func isValidPeer(host *HostInfo) bool {
749
809
return ! (len (host .RPCAddress ()) == 0 ||
750
810
host .hostId == "" ||
751
811
host .dataCenter == "" ||
752
- host .rack == "" ||
812
+ host .missingRack ||
753
813
len (host .tokens ) == 0 )
754
814
}
755
815
0 commit comments