20
20
#include "mongoc-cursor-private.h"
21
21
#include "mongoc-collection-private.h"
22
22
#include "mongoc-client-session-private.h"
23
+ #include "mongoc-rpc-private.h"
23
24
24
25
#define CHANGE_STREAM_ERR (_str ) \
25
26
bson_set_error (&stream->err, \
@@ -88,7 +89,7 @@ _mongoc_change_stream_make_cursor (mongoc_change_stream_t *stream)
88
89
size_t keyLen =
89
90
bson_uint32_to_string (key_int , & key_str , buf , sizeof (buf ));
90
91
bson_append_value (
91
- & pipeline , key_str , keyLen , bson_iter_value (& child_iter ));
92
+ & pipeline , key_str , ( int ) keyLen , bson_iter_value (& child_iter ));
92
93
++ key_int ;
93
94
}
94
95
}
@@ -120,6 +121,31 @@ _mongoc_change_stream_make_cursor (mongoc_change_stream_t *stream)
120
121
stream -> coll -> client , & iter , & cs , & stream -> err )) {
121
122
goto cleanup ;
122
123
}
124
+ } else if (stream -> implicit_session ) {
125
+ /* If an implicit session was created before, and this cursor is now
126
+ * being recreated after resuming, then use the same session as before. */
127
+ cs = stream -> implicit_session ;
128
+ if (!mongoc_client_session_append (cs , & command_opts , & stream -> err )) {
129
+ goto cleanup ;
130
+ }
131
+ } else {
132
+ /* Create an implicit session. This session lsid must be the same for the
133
+ * agg command and the subsequent getMores. Thus, this implicit session is
134
+ * passed as if it were an explicit session to
135
+ * collection_read_command_with_opts and cursor_new_from_reply, but it is
136
+ * still implicit and its lifetime is owned by this change_stream_t. */
137
+ mongoc_session_opt_t * session_opts ;
138
+ session_opts = mongoc_session_opts_new ();
139
+ mongoc_session_opts_set_causal_consistency (session_opts , false);
140
+ /* returns NULL if sessions aren't supported. ignore errors. */
141
+ cs =
142
+ mongoc_client_start_session (stream -> coll -> client , session_opts , NULL );
143
+ stream -> implicit_session = cs ;
144
+ mongoc_session_opts_destroy (session_opts );
145
+ if (cs &&
146
+ !mongoc_client_session_append (cs , & command_opts , & stream -> err )) {
147
+ goto cleanup ;
148
+ }
123
149
}
124
150
125
151
server_id = mongoc_server_description_id (sd );
@@ -161,7 +187,8 @@ _mongoc_change_stream_make_cursor (mongoc_change_stream_t *stream)
161
187
}
162
188
163
189
if (stream -> batch_size > 0 ) {
164
- mongoc_cursor_set_batch_size (stream -> cursor , stream -> batch_size );
190
+ mongoc_cursor_set_batch_size (stream -> cursor ,
191
+ (uint32_t ) stream -> batch_size );
165
192
}
166
193
167
194
cleanup :
@@ -177,7 +204,7 @@ _mongoc_change_stream_new (const mongoc_collection_t *coll,
177
204
{
178
205
bool full_doc_set = false;
179
206
mongoc_change_stream_t * stream =
180
- (mongoc_change_stream_t * ) bson_malloc (sizeof (mongoc_change_stream_t ));
207
+ (mongoc_change_stream_t * ) bson_malloc0 (sizeof (mongoc_change_stream_t ));
181
208
182
209
BSON_ASSERT (coll );
183
210
BSON_ASSERT (pipeline );
@@ -190,8 +217,6 @@ _mongoc_change_stream_new (const mongoc_collection_t *coll,
190
217
bson_init (& stream -> opts );
191
218
bson_init (& stream -> resume_token );
192
219
bson_init (& stream -> err_doc );
193
- memset (& stream -> err , 0 , sizeof (bson_error_t ));
194
- stream -> cursor = NULL ;
195
220
196
221
/*
197
222
* The passed options may consist of:
@@ -260,12 +285,13 @@ bool
260
285
mongoc_change_stream_next (mongoc_change_stream_t * stream , const bson_t * * bson )
261
286
{
262
287
bson_iter_t iter ;
288
+ bool ret = false;
263
289
264
290
BSON_ASSERT (stream );
265
291
BSON_ASSERT (bson );
266
292
267
293
if (stream -> err .code != 0 ) {
268
- return false ;
294
+ goto end ;
269
295
}
270
296
271
297
if (!mongoc_cursor_next (stream -> cursor , bson )) {
@@ -275,7 +301,7 @@ mongoc_change_stream_next (mongoc_change_stream_t *stream, const bson_t **bson)
275
301
276
302
if (!mongoc_cursor_error_document (stream -> cursor , & err , & err_doc )) {
277
303
/* No error occurred, just no documents left */
278
- return false ;
304
+ goto end ;
279
305
}
280
306
281
307
/* Change Streams Spec: An error is resumable if it is not a server error,
@@ -311,7 +337,7 @@ mongoc_change_stream_next (mongoc_change_stream_t *stream, const bson_t **bson)
311
337
!mongoc_cursor_error_document (stream -> cursor , & err , & err_doc );
312
338
if (resumable ) {
313
339
/* Empty batch. */
314
- return false ;
340
+ goto end ;
315
341
}
316
342
}
317
343
}
@@ -320,7 +346,7 @@ mongoc_change_stream_next (mongoc_change_stream_t *stream, const bson_t **bson)
320
346
stream -> err = err ;
321
347
bson_destroy (& stream -> err_doc );
322
348
bson_copy_to (err_doc , & stream -> err_doc );
323
- return false ;
349
+ goto end ;
324
350
}
325
351
}
326
352
@@ -332,14 +358,25 @@ mongoc_change_stream_next (mongoc_change_stream_t *stream, const bson_t **bson)
332
358
MONGOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN ,
333
359
"Cannot provide resume functionality when the resume "
334
360
"token is missing" );
335
- return false ;
361
+ goto end ;
336
362
}
337
363
338
364
/* Copy the resume token */
339
365
bson_reinit (& stream -> resume_token );
340
366
BSON_APPEND_VALUE (
341
367
& stream -> resume_token , "resumeAfter" , bson_iter_value (& iter ));
342
- return true;
368
+ ret = true;
369
+
370
+ end :
371
+ /* Driver Sessions Spec: "When an implicit session is associated with a
372
+ * cursor for use with getMore operations, the session MUST be returned to
373
+ * the pool immediately following a getMore operation that indicates that the
374
+ * cursor has been exhausted." */
375
+ if (stream -> implicit_session && stream -> cursor -> rpc .reply .cursor_id == 0 ) {
376
+ mongoc_client_session_destroy (stream -> implicit_session );
377
+ stream -> implicit_session = NULL ;
378
+ }
379
+ return ret ;
343
380
}
344
381
345
382
bool
@@ -373,6 +410,9 @@ mongoc_change_stream_destroy (mongoc_change_stream_t *stream)
373
410
if (stream -> cursor ) {
374
411
mongoc_cursor_destroy (stream -> cursor );
375
412
}
413
+ if (stream -> implicit_session ) {
414
+ mongoc_client_session_destroy (stream -> implicit_session );
415
+ }
376
416
mongoc_collection_destroy (stream -> coll );
377
417
bson_free (stream );
378
418
}
0 commit comments