@@ -75,9 +75,22 @@ impl LoadBalancingConfig {
75
75
builder =
76
76
builder. enable_shuffling_replicas ( self . token_aware_shuffling_replicas_enabled ) ;
77
77
}
78
- if let LoadBalancingKind :: DcAware { local_dc } = load_balancing_kind {
79
- builder = builder. prefer_datacenter ( local_dc) . permit_dc_failover ( true )
78
+
79
+ match load_balancing_kind {
80
+ LoadBalancingKind :: DcAware { local_dc } => {
81
+ builder = builder. prefer_datacenter ( local_dc) . permit_dc_failover ( true )
82
+ }
83
+ LoadBalancingKind :: RackAware {
84
+ local_dc,
85
+ local_rack,
86
+ } => {
87
+ builder = builder
88
+ . prefer_datacenter_and_rack ( local_dc, local_rack)
89
+ . permit_dc_failover ( true )
90
+ }
91
+ LoadBalancingKind :: RoundRobin => { }
80
92
}
93
+
81
94
if self . latency_awareness_enabled {
82
95
builder = builder. latency_awareness ( self . latency_awareness_builder ) ;
83
96
}
@@ -99,7 +112,13 @@ impl Default for LoadBalancingConfig {
99
112
#[ derive( Clone , Debug ) ]
100
113
pub ( crate ) enum LoadBalancingKind {
101
114
RoundRobin ,
102
- DcAware { local_dc : String } ,
115
+ DcAware {
116
+ local_dc : String ,
117
+ } ,
118
+ RackAware {
119
+ local_dc : String ,
120
+ local_rack : String ,
121
+ } ,
103
122
}
104
123
105
124
#[ derive( Clone ) ]
@@ -553,6 +572,68 @@ pub unsafe extern "C" fn cass_cluster_set_load_balance_dc_aware_n(
553
572
)
554
573
}
555
574
575
+ #[ no_mangle]
576
+ pub unsafe extern "C" fn cass_cluster_set_load_balance_rack_aware (
577
+ cluster_raw : * mut CassCluster ,
578
+ local_dc_raw : * const c_char ,
579
+ local_rack_raw : * const c_char ,
580
+ ) -> CassError {
581
+ cass_cluster_set_load_balance_rack_aware_n (
582
+ cluster_raw,
583
+ local_dc_raw,
584
+ strlen ( local_dc_raw) ,
585
+ local_rack_raw,
586
+ strlen ( local_rack_raw) ,
587
+ )
588
+ }
589
+
590
+ #[ no_mangle]
591
+ pub unsafe extern "C" fn cass_cluster_set_load_balance_rack_aware_n (
592
+ cluster_raw : * mut CassCluster ,
593
+ local_dc_raw : * const c_char ,
594
+ local_dc_length : size_t ,
595
+ local_rack_raw : * const c_char ,
596
+ local_rack_length : size_t ,
597
+ ) -> CassError {
598
+ let cluster = ptr_to_ref_mut ( cluster_raw) ;
599
+
600
+ set_load_balance_rack_aware_n (
601
+ & mut cluster. load_balancing_config ,
602
+ local_dc_raw,
603
+ local_dc_length,
604
+ local_rack_raw,
605
+ local_rack_length,
606
+ )
607
+ }
608
+
609
+ pub ( crate ) unsafe fn set_load_balance_rack_aware_n (
610
+ load_balancing_config : & mut LoadBalancingConfig ,
611
+ local_dc_raw : * const c_char ,
612
+ local_dc_length : size_t ,
613
+ local_rack_raw : * const c_char ,
614
+ local_rack_length : size_t ,
615
+ ) -> CassError {
616
+ let ( local_dc, local_rack) = match (
617
+ ptr_to_cstr_n ( local_dc_raw, local_dc_length) ,
618
+ ptr_to_cstr_n ( local_rack_raw, local_rack_length) ,
619
+ ) {
620
+ ( Some ( local_dc_str) , Some ( local_rack_str) )
621
+ if local_dc_length > 0 && local_rack_length > 0 =>
622
+ {
623
+ ( local_dc_str. to_owned ( ) , local_rack_str. to_owned ( ) )
624
+ }
625
+ // One of them either is a null pointer, is an empty string or is not a proper utf-8.
626
+ _ => return CassError :: CASS_ERROR_LIB_BAD_PARAMS ,
627
+ } ;
628
+
629
+ load_balancing_config. load_balancing_kind = Some ( LoadBalancingKind :: RackAware {
630
+ local_dc,
631
+ local_rack,
632
+ } ) ;
633
+
634
+ CassError :: CASS_OK
635
+ }
636
+
556
637
#[ no_mangle]
557
638
pub unsafe extern "C" fn cass_cluster_set_cloud_secure_connection_bundle_n (
558
639
_cluster_raw : * mut CassCluster ,
@@ -891,12 +972,7 @@ mod tests {
891
972
{
892
973
cass_cluster_set_token_aware_routing ( cluster_raw, 0 ) ;
893
974
assert_cass_error_eq ! (
894
- cass_cluster_set_load_balance_dc_aware(
895
- cluster_raw,
896
- "eu\0 " . as_ptr( ) as * const i8 ,
897
- 0 ,
898
- 0
899
- ) ,
975
+ cass_cluster_set_load_balance_dc_aware( cluster_raw, c"eu" . as_ptr( ) , 0 , 0 ) ,
900
976
CassError :: CASS_OK
901
977
) ;
902
978
cass_cluster_set_latency_aware_routing ( cluster_raw, 1 ) ;
@@ -920,25 +996,98 @@ mod tests {
920
996
}
921
997
assert ! ( !cluster. load_balancing_config. token_awareness_enabled) ;
922
998
assert ! ( cluster. load_balancing_config. latency_awareness_enabled) ;
999
+
1000
+ // set preferred rack+dc
1001
+ assert_cass_error_eq ! (
1002
+ cass_cluster_set_load_balance_rack_aware(
1003
+ cluster_raw,
1004
+ c"eu-east" . as_ptr( ) ,
1005
+ c"rack1" . as_ptr( ) ,
1006
+ ) ,
1007
+ CassError :: CASS_OK
1008
+ ) ;
1009
+
1010
+ let node_location_preference =
1011
+ & cluster. load_balancing_config . load_balancing_kind ;
1012
+ match node_location_preference {
1013
+ Some ( LoadBalancingKind :: RackAware {
1014
+ local_dc,
1015
+ local_rack,
1016
+ } ) => {
1017
+ assert_eq ! ( local_dc, "eu-east" ) ;
1018
+ assert_eq ! ( local_rack, "rack1" ) ;
1019
+ }
1020
+ _ => panic ! ( "Expected preferred dc and rack" ) ,
1021
+ }
1022
+
1023
+ // set back to preferred dc
1024
+ assert_cass_error_eq ! (
1025
+ cass_cluster_set_load_balance_dc_aware( cluster_raw, c"eu" . as_ptr( ) , 0 , 0 ) ,
1026
+ CassError :: CASS_OK
1027
+ ) ;
1028
+
1029
+ let node_location_preference =
1030
+ & cluster. load_balancing_config . load_balancing_kind ;
1031
+ match node_location_preference {
1032
+ Some ( LoadBalancingKind :: DcAware { local_dc } ) => {
1033
+ assert_eq ! ( local_dc, "eu" )
1034
+ }
1035
+ _ => panic ! ( "Expected preferred dc" ) ,
1036
+ }
923
1037
}
924
1038
/* Test invalid configurations */
925
1039
{
926
1040
// Nonzero deprecated parameters
927
1041
assert_cass_error_eq ! (
928
- cass_cluster_set_load_balance_dc_aware(
1042
+ cass_cluster_set_load_balance_dc_aware( cluster_raw, c"eu" . as_ptr( ) , 1 , 0 ) ,
1043
+ CassError :: CASS_ERROR_LIB_BAD_PARAMS
1044
+ ) ;
1045
+ assert_cass_error_eq ! (
1046
+ cass_cluster_set_load_balance_dc_aware( cluster_raw, c"eu" . as_ptr( ) , 0 , 1 ) ,
1047
+ CassError :: CASS_ERROR_LIB_BAD_PARAMS
1048
+ ) ;
1049
+
1050
+ // null pointers
1051
+ assert_cass_error_eq ! (
1052
+ cass_cluster_set_load_balance_dc_aware( cluster_raw, std:: ptr:: null( ) , 0 , 0 ) ,
1053
+ CassError :: CASS_ERROR_LIB_BAD_PARAMS
1054
+ ) ;
1055
+ assert_cass_error_eq ! (
1056
+ cass_cluster_set_load_balance_rack_aware(
1057
+ cluster_raw,
1058
+ c"eu" . as_ptr( ) ,
1059
+ std:: ptr:: null( ) ,
1060
+ ) ,
1061
+ CassError :: CASS_ERROR_LIB_BAD_PARAMS
1062
+ ) ;
1063
+ assert_cass_error_eq ! (
1064
+ cass_cluster_set_load_balance_rack_aware(
1065
+ cluster_raw,
1066
+ std:: ptr:: null( ) ,
1067
+ c"rack" . as_ptr( ) ,
1068
+ ) ,
1069
+ CassError :: CASS_ERROR_LIB_BAD_PARAMS
1070
+ ) ;
1071
+
1072
+ // empty strings
1073
+ let empty_str = "\0 " . as_ptr ( ) as * const i8 ;
1074
+ assert_cass_error_eq ! (
1075
+ cass_cluster_set_load_balance_dc_aware( cluster_raw, std:: ptr:: null( ) , 0 , 0 ) ,
1076
+ CassError :: CASS_ERROR_LIB_BAD_PARAMS
1077
+ ) ;
1078
+ assert_cass_error_eq ! (
1079
+ cass_cluster_set_load_balance_rack_aware(
929
1080
cluster_raw,
930
- "eu\0 " . as_ptr( ) as * const i8 ,
931
- 1 ,
932
- 0
1081
+ c"eu" . as_ptr( ) ,
1082
+ empty_str,
933
1083
) ,
934
1084
CassError :: CASS_ERROR_LIB_BAD_PARAMS
935
1085
) ;
936
1086
assert_cass_error_eq ! (
937
- cass_cluster_set_load_balance_dc_aware (
1087
+ cass_cluster_set_load_balance_rack_aware (
938
1088
cluster_raw,
939
- "eu\0 " . as_ptr( ) as * const i8 ,
940
- 0 ,
941
- 1
1089
+ empty_str,
1090
+ c"rack" . as_ptr( ) ,
942
1091
) ,
943
1092
CassError :: CASS_ERROR_LIB_BAD_PARAMS
944
1093
) ;
0 commit comments