Skip to content

Commit bb0e108

Browse files
committed
CDRIVER-453 remove replica set member limit
o Make the number of replica set member nodes dynamic. o Fix some of the sharding and replica set tests. o Fix a bug in socket error reporting Closes #112
1 parent ae1e220 commit bb0e108

File tree

7 files changed

+87
-43
lines changed

7 files changed

+87
-43
lines changed

src/libbson

Submodule libbson updated 1 file

src/mongoc/mongoc-client.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ _mongoc_client_recv (mongoc_client_t *client,
485485
bson_return_val_if_fail(rpc, false);
486486
bson_return_val_if_fail(buffer, false);
487487
bson_return_val_if_fail(hint, false);
488-
bson_return_val_if_fail(hint <= MONGOC_CLUSTER_MAX_NODES, false);
488+
bson_return_val_if_fail(hint <= client->cluster.nodes_len, false);
489489

490490
return _mongoc_cluster_try_recv (&client->cluster, rpc, buffer, hint,
491491
error);

src/mongoc/mongoc-cluster-private.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
BSON_BEGIN_DECLS
4141

4242

43-
#define MONGOC_CLUSTER_MAX_NODES 12
4443
#define MONGOC_CLUSTER_PING_NUM_SAMPLES 5
4544

4645

@@ -96,7 +95,8 @@ typedef struct
9695

9796
unsigned requires_auth : 1;
9897

99-
mongoc_cluster_node_t nodes[MONGOC_CLUSTER_MAX_NODES];
98+
mongoc_cluster_node_t *nodes;
99+
uint32_t nodes_len;
100100
mongoc_client_t *client;
101101
int32_t max_bson_size;
102102
int32_t max_msg_size;

src/mongoc/mongoc-cluster.c

Lines changed: 75 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ _mongoc_cluster_update_state (mongoc_cluster_t *cluster)
126126

127127
BSON_ASSERT(cluster);
128128

129-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
129+
for (i = 0; i < cluster->nodes_len; i++) {
130130
node = &cluster->nodes[i];
131131
if (node->stamp && !node->stream) {
132132
down_nodes++;
@@ -481,6 +481,7 @@ _mongoc_cluster_init (mongoc_cluster_t *cluster,
481481
void *client)
482482
{
483483
const mongoc_host_list_t *hosts;
484+
const mongoc_host_list_t *host_iter;
484485
uint32_t sockettimeoutms = DEFAULT_SOCKET_TIMEOUT_MSEC;
485486
uint32_t i;
486487
const bson_t *b;
@@ -528,7 +529,16 @@ _mongoc_cluster_init (mongoc_cluster_t *cluster,
528529
cluster->sec_latency_ms = bson_iter_int32(&iter);
529530
}
530531

531-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
532+
if (cluster->mode == MONGOC_CLUSTER_DIRECT) {
533+
i = 1;
534+
} else {
535+
for (host_iter = hosts, i = 0; host_iter; host_iter = host_iter->next, i++) {}
536+
}
537+
538+
cluster->nodes = bson_malloc(i * sizeof(*cluster->nodes));
539+
cluster->nodes_len = i;
540+
541+
for (i = 0; i < cluster->nodes_len; i++) {
532542
_mongoc_cluster_node_init(&cluster->nodes[i]);
533543
cluster->nodes[i].stamp = 0;
534544
cluster->nodes[i].index = i;
@@ -570,12 +580,14 @@ _mongoc_cluster_destroy (mongoc_cluster_t *cluster) /* INOUT */
570580

571581
mongoc_uri_destroy (cluster->uri);
572582

573-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
583+
for (i = 0; i < cluster->nodes_len; i++) {
574584
if (cluster->nodes[i].stream) {
575585
_mongoc_cluster_node_destroy (&cluster->nodes [i]);
576586
}
577587
}
578588

589+
bson_free (cluster->nodes);
590+
579591
bson_free (cluster->replSet);
580592
cluster->replSet = NULL;
581593

@@ -616,30 +628,36 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
616628
const mongoc_read_prefs_t *read_prefs,
617629
bson_error_t *error)
618630
{
619-
mongoc_cluster_node_t *nodes[MONGOC_CLUSTER_MAX_NODES];
631+
mongoc_cluster_node_t **nodes;
620632
mongoc_read_mode_t read_mode = MONGOC_READ_PRIMARY;
621-
int scores[MONGOC_CLUSTER_MAX_NODES];
633+
int *scores;
622634
int max_score = 0;
623635
uint32_t count;
624636
uint32_t watermark;
625637
int32_t nearest = -1;
626638
bool need_primary;
627639
bool need_secondary;
628640
unsigned i;
641+
mongoc_cluster_node_t *node = NULL;
629642

630643
ENTRY;
631644

632645
bson_return_val_if_fail(cluster, NULL);
633646
bson_return_val_if_fail(rpcs, NULL);
634647
bson_return_val_if_fail(rpcs_len, NULL);
635-
bson_return_val_if_fail(hint <= MONGOC_CLUSTER_MAX_NODES, NULL);
648+
bson_return_val_if_fail(hint <= cluster->nodes_len, NULL);
649+
650+
nodes = bson_malloc(sizeof(*nodes) * cluster->nodes_len);
651+
scores = bson_malloc(sizeof(*scores) * cluster->nodes_len);
636652

637653
/*
638654
* We can take a few short-cut's if we are not talking to a replica set.
639655
*/
640656
switch (cluster->mode) {
641-
case MONGOC_CLUSTER_DIRECT:
642-
RETURN (cluster->nodes[0].stream ? &cluster->nodes[0] : NULL);
657+
case MONGOC_CLUSTER_DIRECT: {
658+
node = (cluster->nodes[0].stream ? &cluster->nodes[0] : NULL);
659+
goto CLEANUP;
660+
}
643661
case MONGOC_CLUSTER_SHARDED_CLUSTER:
644662
need_primary = false;
645663
need_secondary = false;
@@ -690,9 +708,10 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
690708
* Build our list of nodes with established connections. Short circuit if
691709
* we require a primary and we found one.
692710
*/
693-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
711+
for (i = 0; i < cluster->nodes_len; i++) {
694712
if (need_primary && cluster->nodes[i].primary) {
695-
RETURN(&cluster->nodes[i]);
713+
node = &cluster->nodes[i];
714+
goto CLEANUP;
696715
} else if (need_secondary && cluster->nodes[i].primary) {
697716
nodes[i] = NULL;
698717
} else {
@@ -708,7 +727,7 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
708727
MONGOC_ERROR_CLIENT,
709728
MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER,
710729
"Requested PRIMARY node is not available.");
711-
RETURN(NULL);
730+
goto CLEANUP;
712731
}
713732

714733
/*
@@ -723,7 +742,8 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
723742
"Requested node (%u) is not available.",
724743
hint);
725744
}
726-
RETURN(nodes[hint - 1]);
745+
node = nodes[hint - 1];
746+
goto CLEANUP;
727747
}
728748

729749
/*
@@ -743,7 +763,7 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
743763

744764
count = 0;
745765

746-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
766+
for (i = 0; i < cluster->nodes_len; i++) {
747767
if (nodes[i]) {
748768
if (read_prefs) {
749769
int score = _mongoc_read_prefs_score(read_prefs, nodes[i]);
@@ -765,7 +785,7 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
765785
* Filter nodes with score less than highest score.
766786
*/
767787
if (max_score) {
768-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
788+
for (i = 0; i < cluster->nodes_len; i++) {
769789
if (nodes[i] && (scores[i] < max_score)) {
770790
nodes[i] = NULL;
771791
count--;
@@ -779,7 +799,7 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
779799
#define IS_NEARER_THAN(n, msec) \
780800
((msec < 0 && (n)->ping_avg_msec >= 0) || ((n)->ping_avg_msec < msec))
781801

782-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
802+
for (i = 0; i < cluster->nodes_len; i++) {
783803
if (nodes[i]) {
784804
if (IS_NEARER_THAN(nodes[i], nearest)) {
785805
nearest = nodes[i]->ping_avg_msec;
@@ -794,7 +814,7 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
794814
*/
795815
if (nearest != -1) {
796816
watermark = nearest + cluster->sec_latency_ms;
797-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
817+
for (i = 0; i < cluster->nodes_len; i++) {
798818
if (nodes[i]) {
799819
if (nodes[i]->ping_avg_msec > (int32_t)watermark) {
800820
nodes[i] = NULL;
@@ -812,23 +832,29 @@ _mongoc_cluster_select (mongoc_cluster_t *cluster,
812832
MONGOC_ERROR_CLIENT,
813833
MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER,
814834
"Failed to locate a suitable MongoDB node.");
815-
RETURN (NULL);
835+
goto CLEANUP;
816836
}
817837

818838
/*
819839
* Choose a cluster node within threshold at random.
820840
*/
821841
count = count ? rand() % count : count;
822-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
842+
for (i = 0; i < cluster->nodes_len; i++) {
823843
if (nodes[i]) {
824844
if (!count) {
825-
RETURN(nodes[i]);
845+
node = nodes[i];
846+
goto CLEANUP;
826847
}
827848
count--;
828849
}
829850
}
830851

831-
RETURN(NULL);
852+
CLEANUP:
853+
854+
bson_free(nodes);
855+
bson_free(scores);
856+
857+
RETURN(node);
832858
}
833859

834860

@@ -842,19 +868,24 @@ _mongoc_cluster_preselect (mongoc_cluster_t *cluster, /* IN */
842868
mongoc_cluster_node_t *node;
843869
mongoc_rpc_t rpc = {{ 0 }};
844870
int retry_count = 0;
871+
bson_error_t scoped_error;
845872

846873
BSON_ASSERT (cluster);
847874

848875
rpc.header.opcode = opcode;
849876

850877
while (!(node = _mongoc_cluster_select (cluster, &rpc, 1, 0, write_concern,
851-
read_prefs, error))) {
878+
read_prefs, &scoped_error))) {
852879
if ((retry_count++ == MAX_RETRY_COUNT) ||
853880
!_mongoc_cluster_reconnect (cluster, error)) {
854881
break;
855882
}
856883
}
857884

885+
if (!node && error) {
886+
memcpy (error, &scoped_error, sizeof (scoped_error));
887+
}
888+
858889
return node ? (node->index + 1) : 0;
859890
}
860891

@@ -1997,7 +2028,7 @@ _mongoc_cluster_reconnect_replica_set (mongoc_cluster_t *cluster,
19972028
const mongoc_host_list_t *hosts;
19982029
const mongoc_host_list_t *iter;
19992030
mongoc_cluster_node_t node;
2000-
mongoc_cluster_node_t saved_nodes [MONGOC_CLUSTER_MAX_NODES];
2031+
mongoc_cluster_node_t *saved_nodes;
20012032
mongoc_host_list_t host;
20022033
mongoc_stream_t *stream;
20032034
mongoc_list_t *list;
@@ -2006,20 +2037,23 @@ _mongoc_cluster_reconnect_replica_set (mongoc_cluster_t *cluster,
20062037
const char *replSet;
20072038
int i;
20082039
int j;
2040+
bool rval = false;
20092041

20102042
ENTRY;
20112043

20122044
BSON_ASSERT(cluster);
20132045
BSON_ASSERT(cluster->mode == MONGOC_CLUSTER_REPLICA_SET);
20142046

2047+
saved_nodes = bson_malloc0(cluster->nodes_len * sizeof(*saved_nodes));
2048+
20152049
MONGOC_DEBUG("Reconnecting to replica set.");
20162050

20172051
if (!(hosts = mongoc_uri_get_hosts(cluster->uri))) {
20182052
bson_set_error(error,
20192053
MONGOC_ERROR_CLIENT,
20202054
MONGOC_ERROR_CLIENT_NOT_READY,
20212055
"Invalid host list supplied.");
2022-
RETURN(false);
2056+
goto CLEANUP;
20232057
}
20242058

20252059
replSet = mongoc_uri_get_replica_set(cluster->uri);
@@ -2098,9 +2132,7 @@ _mongoc_cluster_reconnect_replica_set (mongoc_cluster_t *cluster,
20982132
* we don't waste time doing that again.
20992133
*/
21002134

2101-
memset (saved_nodes, 0, sizeof saved_nodes);
2102-
2103-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
2135+
for (i = 0; i < cluster->nodes_len; i++) {
21042136
if (cluster->nodes [i].stream) {
21052137
saved_nodes [i].host = cluster->nodes [i].host;
21062138
saved_nodes [i].stream = cluster->nodes [i].stream;
@@ -2109,7 +2141,7 @@ _mongoc_cluster_reconnect_replica_set (mongoc_cluster_t *cluster,
21092141
}
21102142

21112143
for (liter = list, i = 0;
2112-
liter && (i < MONGOC_CLUSTER_MAX_NODES);
2144+
liter && (i < cluster->nodes_len);
21132145
liter = liter->next) {
21142146

21152147
if (!_mongoc_host_list_from_string(&host, liter->data)) {
@@ -2120,7 +2152,7 @@ _mongoc_cluster_reconnect_replica_set (mongoc_cluster_t *cluster,
21202152

21212153
stream = NULL;
21222154

2123-
for (j = 0; j < MONGOC_CLUSTER_MAX_NODES; j++) {
2155+
for (j = 0; j < cluster->nodes_len; j++) {
21242156
if (0 == strcmp (saved_nodes [j].host.host_and_port,
21252157
host.host_and_port)) {
21262158
stream = saved_nodes [j].stream;
@@ -2162,7 +2194,7 @@ _mongoc_cluster_reconnect_replica_set (mongoc_cluster_t *cluster,
21622194
if (cluster->nodes[i].needs_auth) {
21632195
if (!_mongoc_cluster_auth_node (cluster, &cluster->nodes[i], error)) {
21642196
_mongoc_cluster_node_destroy (&cluster->nodes[i]);
2165-
RETURN (false);
2197+
goto CLEANUP;
21662198
}
21672199
cluster->nodes[i].needs_auth = false;
21682200
}
@@ -2188,7 +2220,7 @@ _mongoc_cluster_reconnect_replica_set (mongoc_cluster_t *cluster,
21882220
* Cleanup all potential saved connections that were not used.
21892221
*/
21902222

2191-
for (j = 0; j < MONGOC_CLUSTER_MAX_NODES; j++) {
2223+
for (j = 0; j < cluster->nodes_len; j++) {
21922224
if (saved_nodes [j].stream) {
21932225
mongoc_stream_destroy (saved_nodes [j].stream);
21942226
saved_nodes [j].stream = NULL;
@@ -2200,12 +2232,18 @@ _mongoc_cluster_reconnect_replica_set (mongoc_cluster_t *cluster,
22002232
MONGOC_ERROR_CLIENT,
22012233
MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER,
22022234
"No acceptable peer could be found.");
2203-
RETURN(false);
2235+
goto CLEANUP;
22042236
}
22052237

22062238
_mongoc_cluster_update_state (cluster);
22072239

2208-
RETURN(true);
2240+
rval = true;
2241+
2242+
CLEANUP:
2243+
2244+
bson_free(saved_nodes);
2245+
2246+
RETURN(rval);
22092247
}
22102248

22112249

@@ -2360,7 +2398,7 @@ _mongoc_cluster_reconnect (mongoc_cluster_t *cluster,
23602398
*
23612399
* TODO: We could be better about reusing connections.
23622400
*/
2363-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
2401+
for (i = 0; i < cluster->nodes_len; i++) {
23642402
if (cluster->nodes [i].stream) {
23652403
mongoc_stream_close (cluster->nodes [i].stream);
23662404
mongoc_stream_destroy (cluster->nodes [i].stream);
@@ -2415,7 +2453,7 @@ _mongoc_cluster_command_early (mongoc_cluster_t *cluster,
24152453

24162454
node = _mongoc_cluster_get_primary (cluster);
24172455

2418-
for (i = 0; !node && i < MONGOC_CLUSTER_MAX_NODES; i++) {
2456+
for (i = 0; !node && i < cluster->nodes_len; i++) {
24192457
if (cluster->nodes[i].stream) {
24202458
node = &cluster->nodes[i];
24212459
}
@@ -2902,7 +2940,7 @@ _mongoc_cluster_try_recv (mongoc_cluster_t *cluster,
29022940
bson_return_val_if_fail (rpc, false);
29032941
bson_return_val_if_fail (buffer, false);
29042942
bson_return_val_if_fail (hint, false);
2905-
bson_return_val_if_fail (hint <= MONGOC_CLUSTER_MAX_NODES, false);
2943+
bson_return_val_if_fail (hint <= cluster->nodes_len, false);
29062944

29072945
/*
29082946
* Fetch the node to communicate over.
@@ -2996,7 +3034,7 @@ _mongoc_cluster_stamp (const mongoc_cluster_t *cluster,
29963034
{
29973035
bson_return_val_if_fail(cluster, 0);
29983036
bson_return_val_if_fail(node > 0, 0);
2999-
bson_return_val_if_fail(node <= MONGOC_CLUSTER_MAX_NODES, 0);
3037+
bson_return_val_if_fail(node <= cluster->nodes_len, 0);
30003038

30013039
return cluster->nodes[node].stamp;
30023040
}
@@ -3017,7 +3055,7 @@ _mongoc_cluster_get_primary (mongoc_cluster_t *cluster)
30173055

30183056
BSON_ASSERT (cluster);
30193057

3020-
for (i = 0; i < MONGOC_CLUSTER_MAX_NODES; i++) {
3058+
for (i = 0; i < cluster->nodes_len; i++) {
30213059
if (cluster->nodes[i].primary) {
30223060
return &cluster->nodes[i];
30233061
}

0 commit comments

Comments
 (0)