@@ -131,6 +131,12 @@ _mongoc_topology_scanner_setup_err_cb (uint32_t id,
131
131
132
132
topology = (mongoc_topology_t * ) data ;
133
133
134
+ if (topology -> description .type == MONGOC_TOPOLOGY_LOAD_BALANCED ) {
135
+ /* In load balanced mode, scanning is only for connection establishment. It must not modify the topology description. */
136
+ MONGOC_DEBUG ("Ignoring scanner error in load balanced mode" );
137
+ return ;
138
+ }
139
+
134
140
mongoc_topology_description_handle_hello (& topology -> description ,
135
141
id ,
136
142
NULL /* hello reply */ ,
@@ -167,7 +173,14 @@ _mongoc_topology_scanner_cb (uint32_t id,
167
173
168
174
topology = (mongoc_topology_t * ) data ;
169
175
176
+ if (topology -> description .type == MONGOC_TOPOLOGY_LOAD_BALANCED ) {
177
+ /* In load balanced mode, scanning is only for connection establishment. It must not modify the topology description. */
178
+ MONGOC_DEBUG ("Ignoring hello response in callback in load balanced mode" );
179
+ return ;
180
+ }
181
+
170
182
bson_mutex_lock (& topology -> mutex );
183
+
171
184
sd = mongoc_topology_description_server_by_id (
172
185
& topology -> description , id , NULL );
173
186
@@ -818,7 +831,9 @@ _mongoc_topology_do_blocking_scan (mongoc_topology_t *topology,
818
831
{
819
832
_mongoc_handshake_freeze ();
820
833
834
+ // LBTODO: don't even bother locking the mutex, note that this is for single-threaded clients only.
821
835
bson_mutex_lock (& topology -> mutex );
836
+ // LBTODO if this is a load balanced cluster, then do not obey cooldown.
822
837
mongoc_topology_scan_once (topology , true /* obey cooldown */ );
823
838
bson_mutex_unlock (& topology -> mutex );
824
839
mongoc_topology_scanner_get_error (topology -> scanner , error );
@@ -945,6 +960,64 @@ mongoc_topology_select (mongoc_topology_t *topology,
945
960
}
946
961
}
947
962
963
+ /* Bypasses normal server selection behavior for a load balanced topology. Returns the id of the one load balancer server. Returns 0 on failure.
964
+ * Successful post-condition: On a single threaded client, a connection will have been established.
965
+ */
966
+ static uint32_t
967
+ _mongoc_topology_select_server_id_loadbalanced (mongoc_topology_t * topology ,
968
+ bson_error_t * error )
969
+ {
970
+ mongoc_server_description_t * selected_server ;
971
+ int32_t selected_server_id ;
972
+ mongoc_topology_scanner_node_t * node ;
973
+ bson_error_t scanner_error = {0 };
974
+
975
+ bson_mutex_lock (& topology -> mutex );
976
+
977
+ BSON_ASSERT (topology -> description .type == MONGOC_TOPOLOGY_LOAD_BALANCED );
978
+
979
+ /* Emit the opening SDAM events if they have not emitted already. */
980
+ _mongoc_topology_description_monitor_opening (& topology -> description );
981
+ selected_server =
982
+ mongoc_topology_description_select (& topology -> description ,
983
+ MONGOC_SS_WRITE ,
984
+ NULL /* read prefs */ ,
985
+ 0 /* local threshold */ );
986
+
987
+ if (!selected_server ) {
988
+ _mongoc_server_selection_error (
989
+ "No suitable server found in load balanced deployment" , NULL , error );
990
+ bson_mutex_unlock (& topology -> mutex );
991
+ return 0 ;
992
+ }
993
+
994
+ selected_server_id = selected_server -> id ;
995
+ bson_mutex_unlock (& topology -> mutex );
996
+
997
+ if (!topology -> single_threaded ) {
998
+ return selected_server_id ;
999
+ }
1000
+
1001
+ /* If this is a single threaded topology, we must ensure that a connection is available to this server. Wrapping drivers make the assumption that successful server selection implies a connection is available. */
1002
+ node = mongoc_topology_scanner_get_node (topology -> scanner , selected_server_id );
1003
+ if (!node ) {
1004
+ _mongoc_server_selection_error ("Topology scanner in invalid state; cannot find load balancer" , NULL , error );
1005
+ return 0 ;
1006
+ }
1007
+
1008
+ if (!node -> stream ) {
1009
+ MONGOC_DEBUG ("server selection performing scan since no connection has been established" );
1010
+ _mongoc_topology_do_blocking_scan (topology , & scanner_error );
1011
+ }
1012
+
1013
+ if (!node -> stream ) {
1014
+ _mongoc_server_selection_error ("Topology scanner in invalid state; cannot find load balancer" , & scanner_error , error );
1015
+ return 0 ;
1016
+ }
1017
+
1018
+ return selected_server_id ;
1019
+ }
1020
+
948
1021
/*
949
1022
*-------------------------------------------------------------------------
950
1023
*
@@ -999,6 +1072,13 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology,
999
1072
bson_mutex_unlock (& topology -> mutex );
1000
1073
return 0 ;
1001
1074
}
1075
+
1076
+ if (topology -> description .type == MONGOC_TOPOLOGY_LOAD_BALANCED ) {
1077
+ bson_mutex_unlock (& topology -> mutex );
1078
+ MONGOC_DEBUG ("bypassing server selection for load balanced topology" );
1079
+ return _mongoc_topology_select_server_id_loadbalanced (topology , error );
1080
+ }
1081
+
1002
1082
bson_mutex_unlock (& topology -> mutex );
1003
1083
1004
1084
heartbeat_msec = topology -> description .heartbeat_msec ;
@@ -1011,21 +1091,6 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology,
1011
1091
if (topology -> single_threaded ) {
1012
1092
_mongoc_topology_description_monitor_opening (& topology -> description );
1013
1093
1014
- if (topology -> description .type == MONGOC_TOPOLOGY_LOAD_BALANCED ) {
1015
- /* Bypass server selection loop. Always select the only server. */
1016
- // LBTODO: this will not work for PHP. Single threaded server selection must imply connection establishment.
1017
- selected_server = mongoc_topology_description_select (
1018
- & topology -> description , optype , read_prefs , local_threshold_ms );
1019
-
1020
- if (!selected_server ) {
1021
- _mongoc_server_selection_error (
1022
- "No suitable server found in load balanced deployment" ,
1023
- NULL ,
1024
- error );
1025
- return 0 ;
1026
- }
1027
- }
1028
-
1029
1094
tried_once = false;
1030
1095
next_update = topology -> last_scan + heartbeat_msec * 1000 ;
1031
1096
if (next_update < loop_start ) {
@@ -1123,18 +1188,6 @@ mongoc_topology_select_server_id (mongoc_topology_t *topology,
1123
1188
selected_server = mongoc_topology_description_select (
1124
1189
& topology -> description , optype , read_prefs , local_threshold_ms );
1125
1190
1126
- if (topology -> description .type == MONGOC_TOPOLOGY_LOAD_BALANCED ) {
1127
- /* Bypass server selection loop. Always select the only server. */
1128
- if (!selected_server ) {
1129
- bson_mutex_unlock (& topology -> mutex );
1130
- _mongoc_server_selection_error (
1131
- "No suitable server found in load balanced deployment" ,
1132
- NULL ,
1133
- error );
1134
- return 0 ;
1135
- }
1136
- }
1137
-
1138
1191
if (!selected_server ) {
1139
1192
TRACE (
1140
1193
"server selection requesting an immediate scan, want %s" ,
@@ -1304,6 +1357,8 @@ mongoc_topology_invalidate_server (mongoc_topology_t *topology,
1304
1357
{
1305
1358
BSON_ASSERT (error );
1306
1359
1360
+ // LBTODO: do not update in load balanced mode.
1361
+
1307
1362
bson_mutex_lock (& topology -> mutex );
1308
1363
mongoc_topology_description_invalidate_server (
1309
1364
& topology -> description , id , error );
@@ -1332,6 +1387,14 @@ _mongoc_topology_update_from_handshake (mongoc_topology_t *topology,
1332
1387
1333
1388
bson_mutex_lock (& topology -> mutex );
1334
1389
1390
+ // LBTODO: do not update the topology if this is load balanced mode.
1391
+ if (topology -> description .type == MONGOC_TOPOLOGY_LOAD_BALANCED ) {
1392
+ /* In load balanced mode, scanning is only for connection establishment. It must not modify the topology description. */
1393
+ MONGOC_DEBUG ("Ignoring handshake response in load balanced mode" );
1394
+ bson_mutex_unlock (& topology -> mutex );
1395
+ return true;
1396
+ }
1397
+
1335
1398
/* return false if server was removed from topology */
1336
1399
has_server = _mongoc_topology_update_no_lock (sd -> id ,
1337
1400
& sd -> last_hello_response ,
@@ -1743,6 +1806,7 @@ _mongoc_topology_handle_app_error (mongoc_topology_t *topology,
1743
1806
}
1744
1807
1745
1808
if (type == MONGOC_SDAM_APP_ERROR_NETWORK ) {
1809
+ // LBTODO: bypass this in load balanced mode.
1746
1810
/* Mark server as unknown. */
1747
1811
mongoc_topology_description_invalidate_server (
1748
1812
& topology -> description , server_id , why );
@@ -1758,6 +1822,7 @@ _mongoc_topology_handle_app_error (mongoc_topology_t *topology,
1758
1822
return false;
1759
1823
}
1760
1824
/* Mark server as unknown. */
1825
+ // LBTODO: bypass this in load balanced mode.
1761
1826
mongoc_topology_description_invalidate_server (
1762
1827
& topology -> description , server_id , why );
1763
1828
_mongoc_topology_clear_connection_pool (topology , server_id );
@@ -1812,6 +1877,7 @@ _mongoc_topology_handle_app_error (mongoc_topology_t *topology,
1812
1877
* error and the error's topologyVersion is strictly greater than the
1813
1878
* current ServerDescription's topologyVersion it MUST replace the
1814
1879
* server's description with a ServerDescription of type Unknown. */
1880
+ // LBTODO: bypass this in load balanced mode.
1815
1881
mongoc_topology_description_invalidate_server (
1816
1882
& topology -> description , server_id , & cmd_error );
1817
1883
0 commit comments