Skip to content

Commit ac37cee

Browse files
author
Christian Hergert
committed
cluster: be resilient about no replicaSet value.
If we think we are connecting to a sharded cluster, (due to no replicaSet being specified) and the first node in the seed list is not a mongos (isdbgrid), then change modes to replicaSet and reconnect. Fixes CDRIVER-312.
1 parent fa45d53 commit ac37cee

File tree

3 files changed

+38
-18
lines changed

3 files changed

+38
-18
lines changed

src/mongoc/mongoc-cluster-private.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ typedef struct
7171
bson_t tags;
7272
unsigned primary : 1;
7373
unsigned needs_auth : 1;
74+
unsigned isdbgrid : 1;
7475
int32_t min_wire_version;
7576
int32_t max_wire_version;
7677
int32_t max_write_batch_size;
@@ -91,7 +92,6 @@ typedef struct
9192
mongoc_uri_t *uri;
9293

9394
unsigned requires_auth : 1;
94-
unsigned isdbgrid : 1;
9595

9696
int32_t wire_version;
9797

@@ -103,6 +103,8 @@ typedef struct
103103
mongoc_array_t iov;
104104

105105
mongoc_list_t *peers;
106+
107+
char *replSet;
106108
} mongoc_cluster_t;
107109

108110

src/mongoc/mongoc-cluster.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,12 @@ _mongoc_cluster_node_destroy (mongoc_cluster_node_t *node)
384384
node->stream = NULL;
385385
}
386386

387-
bson_destroy(&node->tags);
387+
if (node->tags.len) {
388+
bson_destroy (&node->tags);
389+
memset (&node->tags, 0, sizeof node->tags);
390+
}
388391

389-
bson_free(node->replSet);
392+
bson_free (node->replSet);
390393
node->replSet = NULL;
391394

392395
EXIT;
@@ -541,8 +544,9 @@ _mongoc_cluster_init (mongoc_cluster_t *cluster,
541544
b = mongoc_uri_get_options(uri);
542545
hosts = mongoc_uri_get_hosts(uri);
543546

544-
if (bson_iter_init_find_case(&iter, b, "replicaSet")) {
547+
if (bson_iter_init_find_case (&iter, b, "replicaSet")) {
545548
cluster->mode = MONGOC_CLUSTER_REPLICA_SET;
549+
cluster->replSet = bson_iter_dup_utf8 (&iter, NULL);
546550
MONGOC_INFO("Client initialized in replica set mode.");
547551
} else if (hosts->next) {
548552
cluster->mode = MONGOC_CLUSTER_SHARDED_CLUSTER;
@@ -617,12 +621,13 @@ _mongoc_cluster_destroy (mongoc_cluster_t *cluster) /* INOUT */
617621

618622
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
619623
if (cluster->nodes[i].stream) {
620-
mongoc_stream_destroy (cluster->nodes[i].stream);
621-
cluster->nodes[i].stream = NULL;
622-
cluster->nodes[i].stamp++;
624+
_mongoc_cluster_node_destroy (&cluster->nodes [i]);
623625
}
624626
}
625627

628+
bson_free (cluster->replSet);
629+
cluster->replSet = NULL;
630+
626631
_mongoc_cluster_clear_peers (cluster);
627632

628633
_mongoc_array_destroy (&cluster->iov);
@@ -982,8 +987,8 @@ _mongoc_cluster_run_command (mongoc_cluster_t *cluster,
982987

983988
static bool
984989
_mongoc_cluster_ismaster (mongoc_cluster_t *cluster,
985-
mongoc_cluster_node_t *node,
986-
bson_error_t *error)
990+
mongoc_cluster_node_t *node,
991+
bson_error_t *error)
987992
{
988993
int32_t v32;
989994
bool ret = false;
@@ -1063,19 +1068,14 @@ _mongoc_cluster_ismaster (mongoc_cluster_t *cluster,
10631068

10641069
if (bson_iter_init_find (&iter, &reply, "msg") &&
10651070
BSON_ITER_HOLDS_UTF8 (&iter) &&
1066-
(strcmp ("isdbgrid", bson_iter_utf8 (&iter, NULL)) == 0)) {
1067-
/* TODO: is this sufficient to detect sharded clusters? */
1068-
1069-
cluster->isdbgrid = true;
1070-
/*
1071-
* TODO: This is actually a sharded cluster!
1072-
*/
1071+
(0 == strcasecmp ("isdbgrid", bson_iter_utf8 (&iter, NULL)))) {
1072+
node->isdbgrid = true;
10731073
if (cluster->mode != MONGOC_CLUSTER_SHARDED_CLUSTER) {
10741074
MONGOC_INFO ("Unexpectedly connected to sharded cluster: %s",
10751075
node->host.host_and_port);
10761076
}
10771077
} else {
1078-
cluster->isdbgrid = false;
1078+
node->isdbgrid = false;
10791079
}
10801080

10811081
/*
@@ -2030,6 +2030,23 @@ _mongoc_cluster_reconnect_sharded_cluster (mongoc_cluster_t *cluster,
20302030

20312031
_mongoc_cluster_node_track_ping (&cluster->nodes[i], ping);
20322032

2033+
/*
2034+
* If this node is not a mongos, we should fail unless no
2035+
* replicaSet was specified. If that is the case, we will assume
2036+
* the caller meant they wanted a replicaSet and migrate to that
2037+
* reconnection strategy.
2038+
*/
2039+
if ((i == 0) &&
2040+
!cluster->nodes [i].isdbgrid &&
2041+
!mongoc_uri_get_replica_set (cluster->uri) &&
2042+
cluster->nodes [i].replSet) {
2043+
MONGOC_WARNING ("Found replicaSet, expected sharded cluster. "
2044+
"Reconnecting as replicaSet.");
2045+
cluster->mode = MONGOC_CLUSTER_REPLICA_SET;
2046+
cluster->replSet = bson_strdup (cluster->nodes [i].replSet);
2047+
return _mongoc_cluster_reconnect_replica_set (cluster, error);
2048+
}
2049+
20332050
i++;
20342051
}
20352052

src/mongoc/mongoc-cursor.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@ _mongoc_cursor_new (mongoc_client_t *client,
199199
}
200200

201201
/* we can't have exhaust queries with sharded clusters */
202-
if ((flags & MONGOC_QUERY_EXHAUST) && client->cluster.isdbgrid) {
202+
if ((flags & MONGOC_QUERY_EXHAUST) &&
203+
(client->cluster.mode == MONGOC_CLUSTER_SHARDED_CLUSTER)) {
203204
bson_set_error (&cursor->error,
204205
MONGOC_ERROR_CURSOR,
205206
MONGOC_ERROR_CURSOR_INVALID_CURSOR,

0 commit comments

Comments
 (0)