Skip to content

Commit 6f18211

Browse files
committed
CDRIVER-750 don't query recovering RS members
Recovering members are not master, not secondary.
1 parent b74382b commit 6f18211

File tree

8 files changed

+133
-5
lines changed

8 files changed

+133
-5
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ It is my pleasure to announce to you the MongoDB C driver 1.1.10.
66
This is a patch release with bug fixes:
77

88
* Occasional crash reconnecting to replica set.
9+
* Queries sent to recovering replica set members.
910
* Hang after network error sending a large message.
1011

1112
Thanks to everyone who contributed to the development of this point release for

src/mongoc/mongoc-cluster-private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ typedef struct
7474
unsigned primary : 1;
7575
unsigned needs_auth : 1;
7676
unsigned isdbgrid : 1;
77+
unsigned secondary : 1;
7778
int32_t min_wire_version;
7879
int32_t max_wire_version;
7980
int32_t max_write_batch_size;

src/mongoc/mongoc-cluster.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ _mongoc_cluster_node_init (mongoc_cluster_node_t *node)
249249
node->stamp = 0;
250250
bson_init(&node->tags);
251251
node->primary = 0;
252+
node->secondary = 0;
252253
node->needs_auth = 0;
253254
node->valid = true;
254255

@@ -437,6 +438,7 @@ _mongoc_cluster_disconnect_node (mongoc_cluster_t *cluster,
437438
node->pings_pos = 0;
438439
node->stamp++;
439440
node->primary = 0;
441+
node->secondary = 0;
440442

441443
bson_destroy (&node->tags);
442444
bson_init (&node->tags);
@@ -706,7 +708,7 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
706708
if (need_primary && cluster->nodes[i].primary) {
707709
node = &cluster->nodes[i];
708710
goto CLEANUP;
709-
} else if (need_secondary && cluster->nodes[i].primary) {
711+
} else if (need_secondary && !cluster->nodes[i].secondary) {
710712
nodes[i] = NULL;
711713
} else {
712714
nodes[i] = cluster->nodes[i].stream ? &cluster->nodes[i] : NULL;
@@ -1070,6 +1072,7 @@ _mongoc_cluster_ismaster (mongoc_cluster_t *cluster,
10701072
}
10711073

10721074
node->primary = false;
1075+
node->secondary = false;
10731076

10741077
bson_free (node->replSet);
10751078
node->replSet = NULL;
@@ -1080,6 +1083,12 @@ _mongoc_cluster_ismaster (mongoc_cluster_t *cluster,
10801083
node->primary = true;
10811084
}
10821085

1086+
if (bson_iter_init_find_case (&iter, &reply, "secondary") &&
1087+
BSON_ITER_HOLDS_BOOL (&iter) &&
1088+
bson_iter_bool (&iter)) {
1089+
node->secondary = true;
1090+
}
1091+
10831092
if (bson_iter_init_find_case(&iter, &reply, "maxMessageSizeBytes")) {
10841093
v32 = bson_iter_int32(&iter);
10851094
if (!cluster->max_msg_size || (v32 < (int32_t)cluster->max_msg_size)) {
@@ -1974,6 +1983,7 @@ _mongoc_cluster_reconnect_direct (mongoc_cluster_t *cluster,
19741983
node->host = *hosts;
19751984
node->needs_auth = cluster->requires_auth;
19761985
node->primary = false;
1986+
node->secondary = false;
19771987
node->ping_avg_msec = -1;
19781988
memset(node->pings, 0xFF, sizeof node->pings);
19791989
node->pings_pos = 0;

src/mongoc/mongoc-read-prefs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,12 @@ _mongoc_read_prefs_score (const mongoc_read_prefs_t *read_prefs,
292292
bson_return_val_if_fail(read_prefs, -1);
293293
bson_return_val_if_fail(node, -1);
294294

295+
if (!node->primary && !node->secondary) {
296+
/* recovering, arbiter, or removed: see RSOther and RSGhost in
297+
* the Server Discovery And Monitoring Spec */
298+
return -1;
299+
}
300+
295301
switch (read_prefs->mode) {
296302
case MONGOC_READ_PRIMARY:
297303
return _mongoc_read_prefs_score_primary(read_prefs, node);

tests/mock-server.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct _mock_server_t
3434
{
3535
mock_server_handler_t handler;
3636
void *handler_data;
37+
bool verbose;
3738

3839
mongoc_thread_t main_thread;
3940
mongoc_cond_t cond;
@@ -50,6 +51,7 @@ struct _mock_server_t
5051
int last_response_id;
5152

5253
bool isMaster;
54+
bool isSecondary;
5355
int minWireVersion;
5456
int maxWireVersion;
5557
int maxBsonObjectSize;
@@ -150,6 +152,10 @@ handle_ismaster (mock_server_t *server,
150152
BSON_ASSERT (doc);
151153

152154
bson_append_bool (&reply_doc, "ismaster", -1, server->isMaster);
155+
if (!server->isMaster) {
156+
bson_append_bool (&reply_doc, "secondary", -1, server->isSecondary);
157+
}
158+
153159
bson_append_int32 (&reply_doc, "maxBsonObjectSize", -1,
154160
server->maxBsonObjectSize);
155161
bson_append_int32 (&reply_doc, "maxMessageSizeBytes", -1,
@@ -253,7 +259,10 @@ mock_server_worker (void *data)
253259

254260
again:
255261
if (_mongoc_buffer_fill (&buffer, stream, 4, -1, &error) == -1) {
256-
MONGOC_WARNING ("%s():%d: %s", __FUNCTION__, __LINE__, error.message);
262+
if (mock_server_verbose (server)) {
263+
MONGOC_WARNING ("%s():%d: %s", __FUNCTION__, __LINE__, error.message);
264+
}
265+
257266
GOTO (failure);
258267
}
259268

@@ -328,6 +337,8 @@ mock_server_new_rs (const char *address,
328337
mock_server_handler_t handler,
329338
void *handler_data,
330339
const char *setName,
340+
bool isMaster,
341+
bool isSecondary,
331342
const mongoc_host_list_t *hosts)
332343
{
333344
mock_server_t *server;
@@ -343,14 +354,16 @@ mock_server_new_rs (const char *address,
343354
server = bson_malloc0(sizeof *server);
344355
server->handler = handler ? handler : dummy_handler;
345356
server->handler_data = handler_data;
357+
server->verbose = true;
346358
server->sock = NULL;
347359
_mongoc_array_init (&server->streams, sizeof (mongoc_stream_t *));
348360
server->address = address;
349361
server->port = port;
350362

351363
server->minWireVersion = 0;
352364
server->maxWireVersion = 0;
353-
server->isMaster = true;
365+
server->isMaster = isMaster;
366+
server->isSecondary = isSecondary;
354367
server->maxBsonObjectSize = 16777216;
355368
server->maxMessageSizeBytes = 48000000;
356369

@@ -373,7 +386,8 @@ mock_server_new (const char *address,
373386
mock_server_handler_t handler,
374387
void *handler_data)
375388
{
376-
return mock_server_new_rs (address, port, handler, handler_data, NULL, NULL);
389+
return mock_server_new_rs (address, port, handler, handler_data,
390+
NULL, true, false, NULL);
377391
}
378392

379393

@@ -483,6 +497,29 @@ mock_server_run_in_thread (mock_server_t *server)
483497
}
484498

485499

500+
void
501+
mock_server_set_verbose (mock_server_t *server,
502+
bool verbose)
503+
{
504+
mongoc_mutex_lock (&server->mutex);
505+
server->verbose = verbose;
506+
mongoc_mutex_unlock (&server->mutex);
507+
}
508+
509+
510+
bool
511+
mock_server_verbose (mock_server_t *server)
512+
{
513+
bool verbose;
514+
515+
mongoc_mutex_lock (&server->mutex);
516+
verbose = server->verbose;
517+
mongoc_mutex_unlock (&server->mutex);
518+
519+
return verbose;
520+
}
521+
522+
486523
void
487524
mock_server_quit (mock_server_t *server)
488525
{

tests/mock-server.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ mock_server_t *mock_server_new_rs (const char *address,
4747
mock_server_handler_t handler,
4848
void *handler_data,
4949
const char *setName,
50+
bool isMaster,
51+
bool isSecondary,
5052
const mongoc_host_list_t *hosts);
5153
void mock_server_set_wire_version (mock_server_t *server,
5254
int32_t min_wire_version,
@@ -58,6 +60,9 @@ void mock_server_reply_simple (mock_server_t *server,
5860
const bson_t *doc);
5961
int mock_server_run (mock_server_t *server);
6062
void mock_server_run_in_thread (mock_server_t *server);
63+
void mock_server_set_verbose (mock_server_t *server,
64+
bool verbose);
65+
bool mock_server_verbose (mock_server_t *server);
6166
void mock_server_quit (mock_server_t *server);
6267
void mock_server_destroy (mock_server_t *server);
6368

tests/test-mongoc-client.c

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ test_seed_list (bool rs,
534534
hosts = mongoc_uri_get_hosts (uri);
535535

536536
server = mock_server_new_rs ("127.0.0.1", port, NULL, NULL,
537-
rs ? "rs" : NULL, hosts);
537+
rs ? "rs" : NULL, true, false, hosts);
538538

539539
mock_server_run_in_thread (server);
540540

@@ -625,6 +625,61 @@ test_mongos_seeds_reconnect (void)
625625
test_seed_list (false, RECONNECT);
626626
}
627627

628+
static void
629+
test_recovering (void)
630+
{
631+
uint16_t port;
632+
char *uri_str;
633+
mongoc_uri_t *uri;
634+
mock_server_t *server;
635+
uint32_t i;
636+
const mongoc_host_list_t *hosts;
637+
mongoc_client_t *client;
638+
mongoc_read_mode_t read_mode;
639+
mongoc_read_prefs_t *prefs;
640+
bson_error_t error;
641+
642+
port = 20000 + (rand () % 1000);
643+
uri_str = bson_strdup_printf ("mongodb://localhost:%hu/?replicaSet=rs",
644+
port);
645+
646+
uri = mongoc_uri_new (uri_str);
647+
hosts = mongoc_uri_get_hosts (uri);
648+
649+
/* server is "recovering": not master, not secondary */
650+
server = mock_server_new_rs ("127.0.0.1", port, NULL, NULL,
651+
"rs", false, false, hosts);
652+
653+
mock_server_set_verbose (server, false);
654+
mock_server_run_in_thread (server);
655+
656+
client = mongoc_client_new_from_uri (uri);
657+
assert (client);
658+
ASSERT_CMPINT (1, ==, client->cluster.nodes_len);
659+
for (i = 0; i < 1; i++) {
660+
assert (client->cluster.nodes[i].valid);
661+
}
662+
663+
prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY);
664+
665+
/* recovering member matches no read mode */
666+
for (read_mode = MONGOC_READ_PRIMARY;
667+
read_mode <= MONGOC_READ_NEAREST;
668+
read_mode++) {
669+
mongoc_read_prefs_set_mode (prefs, read_mode);
670+
assert (!_mongoc_cluster_preselect (&client->cluster,
671+
MONGOC_OPCODE_QUERY,
672+
NULL, prefs, &error));
673+
}
674+
675+
mongoc_read_prefs_destroy (prefs);
676+
mongoc_client_destroy (client);
677+
mock_server_quit (server);
678+
mock_server_destroy (server);
679+
mongoc_uri_destroy (uri);
680+
bson_free (uri_str);
681+
}
682+
628683

629684
static void
630685
test_exhaust_cursor (void)
@@ -871,6 +926,7 @@ test_client_install (TestSuite *suite)
871926
TestSuite_Add (suite, "/Client/mongos_seeds_no_connect", test_mongos_seeds_no_connect);
872927
TestSuite_Add (suite, "/Client/mongos_seeds_connect", test_mongos_seeds_connect);
873928
TestSuite_Add (suite, "/Client/mongos_seeds_reconnect", test_mongos_seeds_reconnect);
929+
TestSuite_Add (suite, "/Client/recovering", test_recovering);
874930
TestSuite_Add (suite, "/Client/exhaust_cursor", test_exhaust_cursor);
875931
TestSuite_Add (suite, "/Client/server_status", test_server_status);
876932
}

tests/test-mongoc-read-prefs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ test_mongoc_read_prefs_score (void)
1111
{
1212
mongoc_read_prefs_t *read_prefs;
1313
mongoc_cluster_node_t node = { 0 };
14+
mongoc_cluster_node_t recovering = { 0 };
1415
bool valid;
1516
int score;
1617

@@ -19,32 +20,43 @@ test_mongoc_read_prefs_score (void)
1920
ASSERT_CMPINT(valid, ==, 1)
2021

2122
read_prefs = mongoc_read_prefs_new(MONGOC_READ_PRIMARY);
23+
node.secondary = true;
2224

2325
mongoc_read_prefs_set_mode(read_prefs, MONGOC_READ_PRIMARY);
2426
ASSERT_VALID(read_prefs);
2527
score = _mongoc_read_prefs_score(read_prefs, &node);
2628
ASSERT_CMPINT(score, ==, 0);
29+
score = _mongoc_read_prefs_score(read_prefs, &recovering);
30+
ASSERT_CMPINT(score, ==, -1);
2731

2832
mongoc_read_prefs_set_mode(read_prefs, MONGOC_READ_PRIMARY_PREFERRED);
2933
ASSERT_VALID(read_prefs);
3034
score = _mongoc_read_prefs_score(read_prefs, &node);
3135
ASSERT_CMPINT(score, ==, 1);
36+
score = _mongoc_read_prefs_score(read_prefs, &recovering);
37+
ASSERT_CMPINT(score, ==, -1);
3238

3339
mongoc_read_prefs_set_mode(read_prefs, MONGOC_READ_SECONDARY_PREFERRED);
3440
ASSERT_VALID(read_prefs);
3541
score = _mongoc_read_prefs_score(read_prefs, &node);
3642
ASSERT_CMPINT(score, ==, 1);
43+
score = _mongoc_read_prefs_score(read_prefs, &recovering);
44+
ASSERT_CMPINT(score, ==, -1);
3745

3846
mongoc_read_prefs_set_mode(read_prefs, MONGOC_READ_SECONDARY);
3947
ASSERT_VALID(read_prefs);
4048
score = _mongoc_read_prefs_score(read_prefs, &node);
4149
ASSERT_CMPINT(score, ==, 1);
50+
score = _mongoc_read_prefs_score(read_prefs, &recovering);
51+
ASSERT_CMPINT(score, ==, -1);
4252

4353
node.primary = true;
4454
mongoc_read_prefs_set_mode(read_prefs, MONGOC_READ_PRIMARY);
4555
ASSERT_VALID(read_prefs);
4656
score = _mongoc_read_prefs_score(read_prefs, &node);
4757
ASSERT_CMPINT(score, ==, INT_MAX);
58+
score = _mongoc_read_prefs_score(read_prefs, &recovering);
59+
ASSERT_CMPINT(score, ==, -1);
4860

4961
mongoc_read_prefs_destroy(read_prefs);
5062

0 commit comments

Comments
 (0)