Skip to content

Commit 3b88d3e

Browse files
committed
CDRIVER-1447 logic bug with tag_sets
1 parent b86de94 commit 3b88d3e

File tree

1 file changed

+58
-35
lines changed

1 file changed

+58
-35
lines changed

src/mongoc/mongoc-server-description.c

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ static uint8_t kMongocEmptyBson[] = { 5, 0, 0, 0, 0 };
3232

3333
static bson_oid_t kObjectIdZero = { {0} };
3434

35+
static bool _match_tag_set (const mongoc_server_description_t *sd,
36+
bson_iter_t *tag_set_iter);
37+
3538
/* Destroy allocated resources within @description, but don't free it */
3639
void
3740
mongoc_server_description_cleanup (mongoc_server_description_t *sd)
@@ -734,10 +737,10 @@ mongoc_server_description_filter_stale (mongoc_server_description_t **sds,
734737
*
735738
* mongoc_server_description_filter_tags --
736739
*
737-
* Given a set of server descriptions, determine have the correct tags
738-
* as per the Server Selection spec. Determines the number of
739-
* eligible servers, and sets any servers that are NOT eligible to
740-
* NULL in the descriptions set.
740+
* Given a set of server descriptions, set to NULL any that don't
741+
* match the the read preference's tag sets.
742+
*
743+
* https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#tag-set
741744
*
742745
*-------------------------------------------------------------------------
743746
*/
@@ -749,14 +752,9 @@ mongoc_server_description_filter_tags (mongoc_server_description_t **description
749752
{
750753
const bson_t *rp_tags;
751754
bson_iter_t rp_tagset_iter;
752-
bson_iter_t rp_iter;
753-
bson_iter_t sd_iter;
754-
uint32_t rp_len;
755-
uint32_t sd_len;
756-
const char *rp_val;
757-
const char *sd_val;
755+
bson_iter_t tag_set_iter;
758756
bool *sd_matched = NULL;
759-
size_t found;
757+
bool found;
760758
size_t i;
761759

762760
if (!read_prefs) {
@@ -777,7 +775,7 @@ mongoc_server_description_filter_tags (mongoc_server_description_t **description
777775

778776
/* for each read preference tag set */
779777
while (bson_iter_next (&rp_tagset_iter)) {
780-
found = description_len;
778+
found = false;
781779

782780
for (i = 0; i < description_len; i++) {
783781
if (!descriptions[i]) {
@@ -786,29 +784,10 @@ mongoc_server_description_filter_tags (mongoc_server_description_t **description
786784
continue;
787785
}
788786

789-
sd_matched[i] = true;
790-
791-
bson_iter_recurse (&rp_tagset_iter, &rp_iter);
792-
793-
while (bson_iter_next (&rp_iter)) {
794-
rp_val = bson_iter_utf8 (&rp_iter, &rp_len);
795-
796-
if (bson_iter_init_find (&sd_iter, &descriptions[i]->tags, bson_iter_key (&rp_iter))) {
797-
798-
/* If the server description has that key */
799-
sd_val = bson_iter_utf8 (&sd_iter, &sd_len);
800-
801-
if (! (sd_len == rp_len && (0 == memcmp(rp_val, sd_val, rp_len)))) {
802-
/* If the key value doesn't match, no match */
803-
sd_matched[i] = false;
804-
found--;
805-
}
806-
} else {
807-
/* If the server description doesn't have that key, no match */
808-
sd_matched[i] = false;
809-
found--;
810-
break;
811-
}
787+
bson_iter_recurse (&rp_tagset_iter, &tag_set_iter);
788+
sd_matched[i] = _match_tag_set (descriptions[i], &tag_set_iter);
789+
if (sd_matched[i]) {
790+
found = true;
812791
}
813792
}
814793

@@ -823,6 +802,7 @@ mongoc_server_description_filter_tags (mongoc_server_description_t **description
823802
}
824803
}
825804

805+
/* tried each */
826806
for (i = 0; i < description_len; i++) {
827807
if (! sd_matched[i]) {
828808
descriptions[i] = NULL;
@@ -832,3 +812,46 @@ mongoc_server_description_filter_tags (mongoc_server_description_t **description
832812
CLEANUP:
833813
bson_free (sd_matched);
834814
}
815+
816+
817+
/*
818+
*-------------------------------------------------------------------------
819+
*
820+
* _match_tag_set --
821+
*
822+
* Check if a server's tags match one tag set, like
823+
* {'tag1': 'value1', 'tag2': 'value2'}.
824+
*
825+
*-------------------------------------------------------------------------
826+
*/
827+
static bool _match_tag_set (const mongoc_server_description_t *sd,
828+
bson_iter_t *tag_set_iter)
829+
{
830+
bson_iter_t sd_iter;
831+
uint32_t read_pref_tag_len;
832+
uint32_t sd_len;
833+
const char *read_pref_tag;
834+
const char *read_pref_val;
835+
const char *server_val;
836+
837+
while (bson_iter_next (tag_set_iter)) {
838+
/* one {'tag': 'value'} pair from the read preference's tag set */
839+
read_pref_tag = bson_iter_key (tag_set_iter);
840+
read_pref_val = bson_iter_utf8 (tag_set_iter, &read_pref_tag_len);
841+
842+
if (bson_iter_init_find (&sd_iter, &sd->tags, read_pref_tag)) {
843+
/* The server has this tag - does it have the right value? */
844+
server_val = bson_iter_utf8 (&sd_iter, &sd_len);
845+
if (sd_len != read_pref_tag_len ||
846+
memcmp(read_pref_val, server_val, read_pref_tag_len)) {
847+
/* If the values don't match, no match */
848+
return false;
849+
}
850+
} else {
851+
/* If the server description doesn't have that key, no match */
852+
return false;
853+
}
854+
}
855+
856+
return true;
857+
}

0 commit comments

Comments
 (0)