Skip to content

Commit afc62d1

Browse files
committed
CDRIVER-2506 a cursor always uses the same lsid
1 parent dc206ee commit afc62d1

File tree

4 files changed

+100
-20
lines changed

4 files changed

+100
-20
lines changed

src/mongoc/mongoc-cmd-private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ typedef struct _mongoc_cmd_parts_t {
7171
bool prohibit_lsid;
7272
mongoc_cmd_parts_allow_txn_number_t allow_txn_number;
7373
bool is_retryable_write;
74-
bool has_implicit_session;
74+
bool has_temp_session;
7575
mongoc_client_t *client;
7676
} mongoc_cmd_parts_t;
7777

src/mongoc/mongoc-cmd.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ mongoc_cmd_parts_init (mongoc_cmd_parts_t *parts,
3939
parts->prohibit_lsid = false;
4040
parts->allow_txn_number = MONGOC_CMD_PARTS_ALLOW_TXN_NUMBER_UNKNOWN;
4141
parts->is_retryable_write = false;
42-
parts->has_implicit_session = false;
42+
parts->has_temp_session = false;
4343
parts->client = client;
4444
bson_init (&parts->read_concern_document);
4545
bson_init (&parts->extra);
@@ -76,7 +76,6 @@ mongoc_cmd_parts_set_session (mongoc_cmd_parts_t *parts,
7676
BSON_ASSERT (parts);
7777
BSON_ASSERT (!parts->assembled.command);
7878
BSON_ASSERT (!parts->assembled.session);
79-
BSON_ASSERT (bson_empty (&parts->extra));
8079

8180
parts->assembled.session = cs;
8281
}
@@ -622,7 +621,7 @@ mongoc_cmd_parts_assemble (mongoc_cmd_parts_t *parts,
622621

623622
if (cs) {
624623
parts->assembled.session = cs;
625-
parts->has_implicit_session = true;
624+
parts->has_temp_session = true;
626625
}
627626
}
628627

@@ -724,7 +723,8 @@ mongoc_cmd_parts_cleanup (mongoc_cmd_parts_t *parts)
724723
bson_destroy (&parts->extra);
725724
bson_destroy (&parts->assembled_body);
726725

727-
if (parts->has_implicit_session) {
726+
if (parts->has_temp_session) {
727+
/* client session returns its server session to server session pool */
728728
mongoc_client_session_destroy (parts->assembled.session);
729729
}
730730
}

src/mongoc/mongoc-cursor.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,7 @@ _mongoc_cursor_run_command (mongoc_cursor_t *cursor,
13061306
bool is_primary;
13071307
mongoc_read_prefs_t *prefs = NULL;
13081308
char db[MONGOC_NAMESPACE_MAX];
1309+
mongoc_session_opt_t *session_opts;
13091310
bool ret = false;
13101311

13111312
ENTRY;
@@ -1322,11 +1323,6 @@ _mongoc_cursor_run_command (mongoc_cursor_t *cursor,
13221323
GOTO (done);
13231324
}
13241325

1325-
if (!opts || !bson_has_field (opts, "sessionId")) {
1326-
/* use the cursor's explicit session if any */
1327-
mongoc_cmd_parts_set_session (&parts, cursor->client_session);
1328-
}
1329-
13301326
if (opts) {
13311327
bson_iter_init (&iter, opts);
13321328
if (!mongoc_cmd_parts_append_opts (&parts,
@@ -1337,10 +1333,27 @@ _mongoc_cursor_run_command (mongoc_cursor_t *cursor,
13371333
}
13381334
}
13391335

1340-
if (!cursor->client_session && parts.assembled.session) {
1341-
/* opts contains "sessionId" */
1336+
if (parts.assembled.session) {
1337+
/* initial query/aggregate/etc, and opts contains "sessionId" */
1338+
BSON_ASSERT (!cursor->client_session);
1339+
BSON_ASSERT (!cursor->explicit_session);
13421340
cursor->client_session = parts.assembled.session;
13431341
cursor->explicit_session = 1;
1342+
} else if (cursor->client_session) {
1343+
/* a getMore with implicit or explicit session already acquired */
1344+
mongoc_cmd_parts_set_session (&parts, cursor->client_session);
1345+
} else {
1346+
/* try to create an implicit session. not causally consistent. we keep
1347+
* the session but leave cursor->explicit_session as 0, so we use the
1348+
* same lsid for getMores but destroy the session when the cursor dies.
1349+
*/
1350+
session_opts = mongoc_session_opts_new ();
1351+
mongoc_session_opts_set_causal_consistency (session_opts, false);
1352+
/* returns NULL if sessions aren't supported. ignore errors. */
1353+
cursor->client_session =
1354+
mongoc_client_start_session (cursor->client, session_opts, NULL);
1355+
mongoc_cmd_parts_set_session (&parts, cursor->client_session);
1356+
mongoc_session_opts_destroy (session_opts);
13441357
}
13451358

13461359
if (cursor->read_concern->level) {

tests/test-mongoc-client-session.c

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "mongoc.h"
2+
#include "mongoc-cursor-private.h"
23
#include "mongoc-util-private.h"
34
#include "mongoc-collection-private.h"
45
#include "utlist.h"
@@ -56,14 +57,14 @@ test_session_no_crypto (void *ctx)
5657
} while (0)
5758

5859

59-
#define ASSERT_SESSIONS_DIFFER(_lsid_a, _lsid_b) \
60-
do { \
61-
/* need a match context when checking that lsids DON'T match */ \
62-
char errmsg[1000]; \
63-
match_ctx_t ctx = {0}; \
64-
ctx.errmsg = errmsg; \
65-
ctx.errmsg_len = sizeof (errmsg); \
66-
BSON_ASSERT (!match_bson_with_ctx ((_lsid_a), (_lsid_b), false, &ctx)); \
60+
#define ASSERT_SESSIONS_DIFFER(_lsid_a, _lsid_b) \
61+
do { \
62+
/* need a match context when checking that lsids DON'T match */ \
63+
char errmsg[1000]; \
64+
match_ctx_t _ctx = {0}; \
65+
_ctx.errmsg = errmsg; \
66+
_ctx.errmsg_len = sizeof (errmsg); \
67+
BSON_ASSERT (!match_bson_with_ctx ((_lsid_a), (_lsid_b), false, &_ctx)); \
6768
} while (0)
6869

6970

@@ -1917,6 +1918,65 @@ test_find_indexes (session_test_t *test)
19171918
}
19181919

19191920

1921+
#define ASSERT_POOL_SIZE(_topology, _expected_size) \
1922+
do { \
1923+
const mongoc_server_session_t *_tmp; \
1924+
int _n_sessions; \
1925+
CDL_COUNT ((_topology)->session_pool, _tmp, _n_sessions); \
1926+
ASSERT_CMPINT (_n_sessions, ==, (int) (_expected_size)); \
1927+
} while (0)
1928+
1929+
1930+
static void
1931+
test_cursor_implicit_session (void *ctx)
1932+
{
1933+
session_test_t *test;
1934+
mongoc_topology_t *topology;
1935+
mongoc_cursor_t *cursor;
1936+
const bson_t *doc;
1937+
mongoc_client_session_t *cs;
1938+
bson_t find_lsid;
1939+
bson_error_t error;
1940+
1941+
test = session_test_new (CORRECT_CLIENT, NOT_CAUSAL);
1942+
test->expect_explicit_lsid = false;
1943+
topology = test->client->topology;
1944+
cs = mongoc_client_start_session (test->client, NULL, &error);
1945+
ASSERT_OR_PRINT (cs, error);
1946+
1947+
mongoc_collection_drop_with_opts (test->session_collection, NULL, NULL);
1948+
insert_10_docs (test);
1949+
cursor = mongoc_collection_find_with_opts (
1950+
test->collection, tmp_bson ("{}"), &test->opts, NULL);
1951+
1952+
BSON_ASSERT (!cursor->client_session);
1953+
mongoc_cursor_set_batch_size (cursor, 2);
1954+
1955+
/* start the cursor. it makes an implicit session & sends it with "find" */
1956+
BSON_ASSERT (mongoc_cursor_next (cursor, &doc));
1957+
BSON_ASSERT (cursor->client_session);
1958+
BSON_ASSERT (!cursor->explicit_session);
1959+
bson_copy_to (&cursor->client_session->server_session->lsid, &find_lsid);
1960+
ASSERT_POOL_SIZE (topology, 0);
1961+
ASSERT_SESSIONS_MATCH (&test->sent_lsid, &find_lsid);
1962+
1963+
/* push a new server session into the pool */
1964+
mongoc_client_session_destroy (cs);
1965+
ASSERT_POOL_SIZE (topology, 1);
1966+
ASSERT_SESSIONS_DIFFER (&find_lsid, &topology->session_pool->lsid);
1967+
1968+
/* "getMore" uses the same lsid as "find" did */
1969+
bson_reinit (&test->sent_lsid);
1970+
ASSERT_CURSOR_COUNT (9, cursor);
1971+
ASSERT_SESSIONS_MATCH (&test->sent_lsid, &find_lsid);
1972+
ASSERT_OR_PRINT (!mongoc_cursor_error (cursor, &error), error);
1973+
1974+
bson_destroy (&find_lsid);
1975+
mongoc_cursor_destroy (cursor);
1976+
session_test_destroy (test);
1977+
}
1978+
1979+
19201980
static void
19211981
test_cmd_error (void *ctx)
19221982
{
@@ -2247,6 +2307,13 @@ test_session_install (TestSuite *suite)
22472307
suite, "/Session/collection_names", test_collection_names, true);
22482308
add_session_test (suite, "/Session/bulk", test_bulk, false);
22492309
add_session_test (suite, "/Session/find_indexes", test_find_indexes, true);
2310+
TestSuite_AddFull (suite,
2311+
"/Session/cursor_implicit_session",
2312+
test_cursor_implicit_session,
2313+
NULL,
2314+
NULL,
2315+
test_framework_skip_if_no_cluster_time,
2316+
test_framework_skip_if_no_crypto);
22502317
TestSuite_AddFull (suite,
22512318
"/Session/cmd_error",
22522319
test_cmd_error,

0 commit comments

Comments
 (0)