Skip to content

Commit ebb485f

Browse files
committed
CDRIVER-2075 retry ismaster once
Server Discovery and Monitoring Spec: "Once a server is connected, the client MUST change its type to Unknown only after it has retried the server once."
1 parent 5799548 commit ebb485f

File tree

6 files changed

+395
-22
lines changed

6 files changed

+395
-22
lines changed

src/mongoc/mongoc-topology-scanner-private.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,15 @@ mongoc_topology_scanner_new (
104104
void
105105
mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts);
106106

107-
mongoc_topology_scanner_node_t *
107+
void
108108
mongoc_topology_scanner_add (mongoc_topology_scanner_t *ts,
109109
const mongoc_host_list_t *host,
110110
uint32_t id);
111111

112112
void
113-
mongoc_topology_scanner_add_and_scan (mongoc_topology_scanner_t *ts,
114-
const mongoc_host_list_t *host,
115-
uint32_t id,
116-
int64_t timeout_msec);
113+
mongoc_topology_scanner_scan (mongoc_topology_scanner_t *ts,
114+
uint32_t id,
115+
int64_t timeout_msec);
117116

118117
void
119118
mongoc_topology_scanner_node_retire (mongoc_topology_scanner_node_t *node);

src/mongoc/mongoc-topology-scanner.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ mongoc_topology_scanner_destroy (mongoc_topology_scanner_t *ts)
217217
bson_free (ts);
218218
}
219219

220-
mongoc_topology_scanner_node_t *
220+
void
221221
mongoc_topology_scanner_add (mongoc_topology_scanner_t *ts,
222222
const mongoc_host_list_t *host,
223223
uint32_t id)
@@ -234,29 +234,25 @@ mongoc_topology_scanner_add (mongoc_topology_scanner_t *ts,
234234
node->last_used = -1;
235235

236236
DL_APPEND (ts->nodes, node);
237-
238-
return node;
239237
}
240238

241239
void
242-
mongoc_topology_scanner_add_and_scan (mongoc_topology_scanner_t *ts,
243-
const mongoc_host_list_t *host,
244-
uint32_t id,
245-
int64_t timeout_msec)
240+
mongoc_topology_scanner_scan (mongoc_topology_scanner_t *ts,
241+
uint32_t id,
242+
int64_t timeout_msec)
246243
{
247244
mongoc_topology_scanner_node_t *node;
248245

249246
BSON_ASSERT (timeout_msec < INT32_MAX);
250247

251-
node = mongoc_topology_scanner_add (ts, host, id);
248+
node = mongoc_topology_scanner_get_node (ts, id);
252249

253250
/* begin non-blocking connection, don't wait for success */
254251
if (node && mongoc_topology_scanner_node_setup (node, &node->last_error)) {
255252
_begin_ismaster_cmd (ts, node, timeout_msec);
256253
}
257254

258255
/* if setup fails the node stays in the scanner. destroyed after the scan. */
259-
return;
260256
}
261257

262258
void

src/mongoc/mongoc-topology.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ _mongoc_topology_reconcile_add_nodes (void *item, void *ctx)
4646
* this scan. */
4747
if (!mongoc_topology_scanner_get_node (scanner, sd->id) &&
4848
!mongoc_topology_scanner_has_node_for_host (scanner, &sd->host)) {
49-
mongoc_topology_scanner_add_and_scan (
50-
scanner, &sd->host, sd->id, topology->connect_timeout_msec);
49+
mongoc_topology_scanner_add (scanner, &sd->host, sd->id);
50+
mongoc_topology_scanner_scan (
51+
scanner, sd->id, topology->connect_timeout_msec);
5152
}
5253

5354
return true;
@@ -151,16 +152,34 @@ _mongoc_topology_scanner_cb (uint32_t id,
151152
const bson_error_t *error /* IN */)
152153
{
153154
mongoc_topology_t *topology;
155+
mongoc_server_description_t *sd;
154156

155157
BSON_ASSERT (data);
156158

157159
topology = (mongoc_topology_t *) data;
158160

159161
mongoc_mutex_lock (&topology->mutex);
160-
_mongoc_topology_update_no_lock (
161-
id, ismaster_response, rtt_msec, topology, error);
162+
sd = mongoc_topology_description_server_by_id (
163+
&topology->description, id, NULL);
164+
165+
/* Server Discovery and Monitoring Spec: "Once a server is connected, the
166+
* client MUST change its type to Unknown only after it has retried the
167+
* server once." */
168+
if (!ismaster_response && sd && sd->type != MONGOC_SERVER_UNKNOWN) {
169+
_mongoc_topology_update_no_lock (
170+
id, ismaster_response, rtt_msec, topology, error);
171+
172+
/* add another ismaster call to the current scan - the scan continues
173+
* until all commands are done */
174+
mongoc_topology_scanner_scan (
175+
topology->scanner, sd->id, topology->connect_timeout_msec);
176+
} else {
177+
_mongoc_topology_update_no_lock (
178+
id, ismaster_response, rtt_msec, topology, error);
179+
180+
mongoc_cond_broadcast (&topology->cond_client);
181+
}
162182

163-
mongoc_cond_broadcast (&topology->cond_client);
164183
mongoc_mutex_unlock (&topology->mutex);
165184
}
166185

tests/TestSuite.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,23 @@ test_error (const char *format, ...) BSON_GNUC_PRINTF (1, 2);
444444
} \
445445
} while (0)
446446

447+
#define WAIT_UNTIL(_pred) \
448+
do { \
449+
int64_t _start = bson_get_monotonic_time (); \
450+
while (!(_pred)) { \
451+
if (bson_get_monotonic_time () - _start > 10 * 1000 * 1000) { \
452+
fprintf (stderr, \
453+
"Predicate \"%s\" timed out\n" \
454+
" %s:%d %s()\n", \
455+
#_pred, \
456+
__FILE__, \
457+
__LINE__, \
458+
BSON_FUNC); \
459+
abort (); \
460+
} \
461+
} \
462+
} while (0)
463+
447464
#define MAX_TEST_NAME_LENGTH 500
448465

449466

tests/test-mongoc-client.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,6 +2689,7 @@ _test_client_sends_handshake (bool pooled)
26892689
mock_server_run (server);
26902690
uri = mongoc_uri_copy (mock_server_get_uri (server));
26912691
mongoc_uri_set_option_as_int32 (uri, "heartbeatFrequencyMS", heartbeat_ms);
2692+
mongoc_uri_set_option_as_int32 (uri, "connectTimeoutMS", 100);
26922693

26932694
if (pooled) {
26942695
pool = mongoc_client_pool_new (uri);
@@ -2730,7 +2731,12 @@ _test_client_sends_handshake (bool pooled)
27302731
* time the server hangs up */
27312732
request = mock_server_receives_ismaster (server);
27322733
_assert_ismaster_valid (request, false);
2734+
mock_server_hangs_up (request);
2735+
request_destroy (request);
27332736

2737+
/* Client retries once (CDRIVER-2075) */
2738+
request = mock_server_receives_ismaster (server);
2739+
_assert_ismaster_valid (request, true);
27342740
mock_server_hangs_up (request);
27352741
request_destroy (request);
27362742

0 commit comments

Comments
 (0)