Skip to content

Commit 9a0ab6c

Browse files
CDRIVER-4113: Thread-safe pool for server session objects (mongodb#847)
* CXX-4113: Thread-safe pool for server session objects * Remove unused node pointers on server sessions * Track pool size, and don't loop while holding the lock to clear * Cleanup and some redesign of pool API * Declare special pool for server sessions * Mention the LIFO nature of the thread-pool, and the non-conformance of the 'push' operation * auditing the pool is compile-time optional * Remove -Waggregate-return
1 parent e92c6b0 commit 9a0ab6c

15 files changed

+953
-210
lines changed

build/maintainer-flags.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
-Wall
2-
-Waggregate-return
32
-Wdeclaration-after-statement
43
-Wempty-body
54
-Wformat

src/libbson/src/bson/bson-macros.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,5 +301,15 @@
301301
#define BSON_GNUC_DEPRECATED_FOR(f) BSON_GNUC_DEPRECATED
302302
#endif
303303

304+
/**
305+
* @brief Mark the attached declared entity as "possibly-unused."
306+
*
307+
* Does nothing on MSVC.
308+
*/
309+
#if defined(__GNUC__) || defined(__clang__)
310+
#define BSON_MAYBE_UNUSED __attribute__ ((unused))
311+
#else
312+
#define BSON_MAYBE_UNUSED /* Nothing for other compilers */
313+
#endif
304314

305315
#endif /* BSON_MACROS_H */

src/libmongoc/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ set (SOURCES ${SOURCES}
558558
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-topology-description.c
559559
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-topology-description-apm.c
560560
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-topology-scanner.c
561+
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-ts-pool.c
561562
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-uri.c
562563
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-util.c
563564
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-version-functions.c
@@ -615,6 +616,7 @@ set (HEADERS
615616
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-stream-gridfs.h
616617
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-stream-socket.h
617618
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-topology-description.h
619+
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-ts-pool-private.h
618620
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-uri.h
619621
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-version-functions.h
620622
${PROJECT_SOURCE_DIR}/src/mongoc/mongoc-write-concern.h
@@ -998,6 +1000,7 @@ set (test-libmongoc-sources
9981000
${PROJECT_SOURCE_DIR}/tests/test-mongoc-topology-scanner.c
9991001
${PROJECT_SOURCE_DIR}/tests/test-mongoc-topology.c
10001002
${PROJECT_SOURCE_DIR}/tests/test-mongoc-transactions.c
1003+
${PROJECT_SOURCE_DIR}/tests/test-mongoc-ts-pool.c
10011004
${PROJECT_SOURCE_DIR}/tests/test-mongoc-uri.c
10021005
${PROJECT_SOURCE_DIR}/tests/test-mongoc-usleep.c
10031006
${PROJECT_SOURCE_DIR}/tests/test-mongoc-util.c

src/libmongoc/src/mongoc/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ set (src_libmongoc_src_mongoc_DIST_noinst_hs
168168
mongoc-topology-background-monitoring-private.h
169169
mongoc-topology-scanner-private.h
170170
mongoc-trace-private.h
171+
mongoc-ts-pool-private.h
171172
mongoc-uri-private.h
172173
mongoc-util-private.h
173174
mongoc-write-command-private.h
@@ -253,6 +254,7 @@ set (src_libmongoc_src_mongoc_DIST_cs
253254
mongoc-topology-description.c
254255
mongoc-topology-description-apm.c
255256
mongoc-topology-scanner.c
257+
mongoc-ts-pool.c
256258
mongoc-uri.c
257259
mongoc-util.c
258260
mongoc-version-functions.c

src/libmongoc/src/mongoc/mongoc-client-pool.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ mongoc_client_pool_destroy (mongoc_client_pool_t *pool)
185185
EXIT;
186186
}
187187

188-
if (pool->topology->session_pool) {
188+
if (!mongoc_server_session_pool_is_empty (pool->topology->session_pool)) {
189189
client = mongoc_client_pool_pop (pool);
190190
_mongoc_client_end_sessions (client);
191191
mongoc_client_pool_push (pool, client);

src/libmongoc/src/mongoc/mongoc-client-session-private.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ struct _mongoc_session_opt_t {
4545
};
4646

4747
typedef struct _mongoc_server_session_t {
48-
struct _mongoc_server_session_t *prev, *next;
4948
int64_t last_used_usec;
5049
bson_t lsid; /* logical session id */
5150
int64_t txn_number; /* transaction number */
@@ -102,16 +101,17 @@ _mongoc_client_session_handle_reply (mongoc_client_session_t *session,
102101
const char *cmd_name,
103102
const bson_t *reply);
104103

105-
mongoc_server_session_t *
106-
_mongoc_server_session_new (bson_error_t *error);
104+
bool
105+
_mongoc_server_session_init (mongoc_server_session_t *session,
106+
bson_error_t *error);
107+
108+
void
109+
_mongoc_server_session_destroy (mongoc_server_session_t *session);
107110

108111
bool
109112
_mongoc_server_session_timed_out (const mongoc_server_session_t *server_session,
110113
int64_t session_timeout_minutes);
111114

112-
void
113-
_mongoc_server_session_destroy (mongoc_server_session_t *server_session);
114-
115115
mongoc_client_session_t *
116116
_mongoc_client_session_new (mongoc_client_t *client,
117117
mongoc_server_session_t *server_session,

src/libmongoc/src/mongoc/mongoc-client-session.c

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -709,35 +709,26 @@ _mongoc_client_session_handle_reply (mongoc_client_session_t *session,
709709
}
710710
}
711711

712-
713-
mongoc_server_session_t *
714-
_mongoc_server_session_new (bson_error_t *error)
712+
bool
713+
_mongoc_server_session_init (mongoc_server_session_t *self, bson_error_t *error)
715714
{
716715
uint8_t uuid_data[16];
717-
mongoc_server_session_t *s;
718-
719716
ENTRY;
720-
717+
BSON_ASSERT (self);
721718
if (!_mongoc_server_session_uuid (uuid_data, error)) {
722-
RETURN (NULL);
719+
RETURN (false);
723720
}
724-
725-
s = bson_malloc0 (sizeof (mongoc_server_session_t));
726-
s->last_used_usec = SESSION_NEVER_USED;
727-
s->prev = NULL;
728-
s->next = NULL;
729-
bson_init (&s->lsid);
730-
bson_append_binary (
731-
&s->lsid, "id", 2, BSON_SUBTYPE_UUID, uuid_data, sizeof uuid_data);
732-
733721
/* transaction number is a positive integer and will be incremented before
734722
* each use, so ensure it is initialized to zero. */
735-
s->txn_number = 0;
723+
self->txn_number = 0;
724+
self->last_used_usec = SESSION_NEVER_USED;
725+
bson_init (&self->lsid);
726+
BSON_APPEND_BINARY (
727+
&self->lsid, "id", BSON_SUBTYPE_UUID, uuid_data, sizeof uuid_data);
736728

737-
RETURN (s);
729+
RETURN (true);
738730
}
739731

740-
741732
bool
742733
_mongoc_server_session_timed_out (const mongoc_server_session_t *server_session,
743734
int64_t session_timeout_minutes)
@@ -766,14 +757,9 @@ _mongoc_server_session_timed_out (const mongoc_server_session_t *server_session,
766757

767758

768759
void
769-
_mongoc_server_session_destroy (mongoc_server_session_t *server_session)
760+
_mongoc_server_session_destroy (mongoc_server_session_t *self)
770761
{
771-
ENTRY;
772-
773-
bson_destroy (&server_session->lsid);
774-
bson_free (server_session);
775-
776-
EXIT;
762+
bson_destroy (&self->lsid);
777763
}
778764

779765

@@ -806,7 +792,8 @@ _mongoc_client_session_new (mongoc_client_t *client,
806792
DEFAULT_MAX_COMMIT_TIME_MS);
807793

808794
if (opts) {
809-
mongoc_optional_copy (&opts->causal_consistency, &session->opts.causal_consistency);
795+
mongoc_optional_copy (&opts->causal_consistency,
796+
&session->opts.causal_consistency);
810797
mongoc_optional_copy (&opts->snapshot, &session->opts.snapshot);
811798
txn_opts_set (&session->opts.default_txn_opts,
812799
opts->default_txn_opts.read_concern,
@@ -1684,9 +1671,9 @@ mongoc_client_session_destroy (mongoc_client_session_t *session)
16841671
_mongoc_client_push_server_session (session->client,
16851672
session->server_session);
16861673
} else {
1687-
/* If the client has been reset, destroy the server session instead of
1688-
pushing it back into the topology's pool. */
1689-
_mongoc_server_session_destroy (session->server_session);
1674+
/** If the client has been reset, destroy the server session instead of
1675+
* pushing it back into the topology's pool. */
1676+
mongoc_server_session_pool_drop (session->server_session);
16901677
}
16911678

16921679
txn_opts_cleanup (&session->opts.default_txn_opts);

src/libmongoc/src/mongoc/mongoc-client.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3013,7 +3013,7 @@ _mongoc_client_end_sessions (mongoc_client_t *client)
30133013
mongoc_cluster_t *cluster = &client->cluster;
30143014
bool r;
30153015

3016-
if (t->session_pool) {
3016+
while (!mongoc_server_session_pool_is_empty (t->session_pool)) {
30173017
prefs = mongoc_read_prefs_new (MONGOC_READ_PRIMARY_PREFERRED);
30183018
server_id =
30193019
mongoc_topology_select_server_id (t, MONGOC_SS_READ, prefs, &error);
@@ -3087,7 +3087,7 @@ mongoc_client_reset (mongoc_client_t *client)
30873087
client->client_sessions = mongoc_set_new (8, NULL, NULL);
30883088

30893089
/* Server sessions are owned by us, so we clear the pool on reset. */
3090-
_mongoc_topology_clear_session_pool (client->topology);
3090+
mongoc_server_session_pool_clear (client->topology->session_pool);
30913091
}
30923092

30933093
mongoc_change_stream_t *

src/libmongoc/src/mongoc/mongoc-topology-private.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "mongoc-uri.h"
2828
#include "mongoc-client-session-private.h"
2929
#include "mongoc-crypt-private.h"
30+
#include "mongoc-ts-pool-private.h"
3031

3132
#define MONGOC_TOPOLOGY_MIN_HEARTBEAT_FREQUENCY_MS 500
3233
#define MONGOC_TOPOLOGY_SOCKET_CHECK_INTERVAL_MS 5000
@@ -62,6 +63,17 @@ typedef struct _mongoc_rr_data_t {
6263
char *txt_record_opts;
6364
} mongoc_rr_data_t;
6465

66+
struct _mongoc_topology_t;
67+
68+
MONGOC_DECL_SPECIAL_TS_POOL (
69+
mongoc_server_session_t,
70+
mongoc_server_session_pool,
71+
struct _mongoc_topology_t,
72+
/* ctor/dtor/prune are defined in the new_with_params call */
73+
NULL,
74+
NULL,
75+
NULL)
76+
6577
typedef bool (*_mongoc_rr_resolver_fn) (const char *service,
6678
mongoc_rr_type_t rr_type,
6779
mongoc_rr_data_t *rr_data,
@@ -102,7 +114,7 @@ typedef struct _mongoc_topology_t {
102114
bool single_threaded;
103115
bool stale;
104116

105-
mongoc_server_session_t *session_pool;
117+
mongoc_server_session_pool session_pool;
106118

107119
/* Is client side encryption enabled? */
108120
bool cse_enabled;
@@ -215,9 +227,6 @@ _mongoc_topology_push_server_session (mongoc_topology_t *topology,
215227
bool
216228
_mongoc_topology_end_sessions_cmd (mongoc_topology_t *topology, bson_t *cmd);
217229

218-
void
219-
_mongoc_topology_clear_session_pool (mongoc_topology_t *topology);
220-
221230
void
222231
_mongoc_topology_do_blocking_scan (mongoc_topology_t *topology,
223232
bson_error_t *error);
@@ -255,7 +264,7 @@ _mongoc_topology_handle_app_error (mongoc_topology_t *topology,
255264
void
256265
_mongoc_topology_clear_connection_pool (mongoc_topology_t *topology,
257266
uint32_t server_id,
258-
const bson_oid_t* service_id);
267+
const bson_oid_t *service_id);
259268

260269
void
261270
mongoc_topology_rescan_srv (mongoc_topology_t *topology);

0 commit comments

Comments
 (0)