@@ -75,9 +75,22 @@ impl LoadBalancingConfig {
7575 builder =
7676 builder. enable_shuffling_replicas ( self . token_aware_shuffling_replicas_enabled ) ;
7777 }
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 => { }
8092 }
93+
8194 if self . latency_awareness_enabled {
8295 builder = builder. latency_awareness ( self . latency_awareness_builder ) ;
8396 }
@@ -99,7 +112,13 @@ impl Default for LoadBalancingConfig {
99112#[ derive( Clone , Debug ) ]
100113pub ( crate ) enum LoadBalancingKind {
101114 RoundRobin ,
102- DcAware { local_dc : String } ,
115+ DcAware {
116+ local_dc : String ,
117+ } ,
118+ RackAware {
119+ local_dc : String ,
120+ local_rack : String ,
121+ } ,
103122}
104123
105124#[ derive( Clone ) ]
@@ -553,6 +572,68 @@ pub unsafe extern "C" fn cass_cluster_set_load_balance_dc_aware_n(
553572 )
554573}
555574
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+
556637#[ no_mangle]
557638pub unsafe extern "C" fn cass_cluster_set_cloud_secure_connection_bundle_n (
558639 _cluster_raw : * mut CassCluster ,
@@ -891,12 +972,7 @@ mod tests {
891972 {
892973 cass_cluster_set_token_aware_routing ( cluster_raw, 0 ) ;
893974 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 ) ,
900976 CassError :: CASS_OK
901977 ) ;
902978 cass_cluster_set_latency_aware_routing ( cluster_raw, 1 ) ;
@@ -920,25 +996,98 @@ mod tests {
920996 }
921997 assert ! ( !cluster. load_balancing_config. token_awareness_enabled) ;
922998 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+ }
9231037 }
9241038 /* Test invalid configurations */
9251039 {
9261040 // Nonzero deprecated parameters
9271041 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(
9291080 cluster_raw,
930- "eu\0 " . as_ptr( ) as * const i8 ,
931- 1 ,
932- 0
1081+ c"eu" . as_ptr( ) ,
1082+ empty_str,
9331083 ) ,
9341084 CassError :: CASS_ERROR_LIB_BAD_PARAMS
9351085 ) ;
9361086 assert_cass_error_eq ! (
937- cass_cluster_set_load_balance_dc_aware (
1087+ cass_cluster_set_load_balance_rack_aware (
9381088 cluster_raw,
939- "eu\0 " . as_ptr( ) as * const i8 ,
940- 0 ,
941- 1
1089+ empty_str,
1090+ c"rack" . as_ptr( ) ,
9421091 ) ,
9431092 CassError :: CASS_ERROR_LIB_BAD_PARAMS
9441093 ) ;
0 commit comments