Skip to content

Commit d0e54c2

Browse files
author
Christian Hergert
committed
cursor: track changes in bson_reader_read() with regards to EOF.
1 parent de54a0c commit d0e54c2

File tree

2 files changed

+68
-42
lines changed

2 files changed

+68
-42
lines changed

src/mongoc/mongoc-cursor-cursorid.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ _mongoc_cursor_cursorid_next (mongoc_cursor_t *cursor,
8787
bson_iter_document (&cid->first_batch_iter, &data_len, &data);
8888
if (bson_init_static (&cid->first_batch_inline, data, data_len)) {
8989
*bson = &cid->first_batch_inline;
90-
return true;
90+
RETURN (true);
9191
}
9292
}
9393
}
@@ -96,7 +96,7 @@ _mongoc_cursor_cursorid_next (mongoc_cursor_t *cursor,
9696
if (!cursor->rpc.reply.cursor_id) {
9797
cursor->done = true;
9898
*bson = NULL;
99-
return false;
99+
RETURN (false);
100100
}
101101
}
102102

src/mongoc/mongoc-cursor.c

Lines changed: 66 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -457,13 +457,13 @@ _mongoc_cursor_unwrap_failure (mongoc_cursor_t *cursor)
457457
static bool
458458
_mongoc_cursor_query (mongoc_cursor_t *cursor)
459459
{
460+
mongoc_rpc_t rpc;
460461
uint32_t hint;
461462
uint32_t request_id;
462-
mongoc_rpc_t rpc;
463463

464464
ENTRY;
465465

466-
bson_return_val_if_fail(cursor, false);
466+
bson_return_val_if_fail (cursor, false);
467467

468468
if (!_mongoc_client_warm_up (cursor->client, &cursor->error)) {
469469
cursor->failed = true;
@@ -489,7 +489,7 @@ _mongoc_cursor_query (mongoc_cursor_t *cursor)
489489
cursor->hint, NULL,
490490
cursor->read_prefs,
491491
&cursor->error))) {
492-
goto failure;
492+
GOTO (failure);
493493
}
494494

495495
cursor->hint = hint;
@@ -502,7 +502,7 @@ _mongoc_cursor_query (mongoc_cursor_t *cursor)
502502
&cursor->buffer,
503503
hint,
504504
&cursor->error)) {
505-
goto failure;
505+
GOTO (failure);
506506
}
507507

508508
if (cursor->rpc.header.opcode != MONGOC_OPCODE_REPLY) {
@@ -528,7 +528,7 @@ _mongoc_cursor_query (mongoc_cursor_t *cursor)
528528
(cursor->error.code == MONGOC_ERROR_QUERY_NOT_TAILABLE)) {
529529
cursor->failed = true;
530530
}
531-
goto failure;
531+
GOTO (failure);
532532
}
533533

534534
if (cursor->reader) {
@@ -546,12 +546,14 @@ _mongoc_cursor_query (mongoc_cursor_t *cursor)
546546
cursor->done = false;
547547
cursor->end_of_event = false;
548548
cursor->sent = true;
549-
RETURN(true);
549+
550+
RETURN (true);
550551

551552
failure:
552553
cursor->failed = true;
553554
cursor->done = true;
554-
RETURN(false);
555+
556+
RETURN (false);
555557
}
556558

557559

@@ -564,9 +566,9 @@ _mongoc_cursor_get_more (mongoc_cursor_t *cursor)
564566

565567
ENTRY;
566568

567-
BSON_ASSERT(cursor);
569+
BSON_ASSERT (cursor);
568570

569-
if (! cursor->in_exhaust) {
571+
if (!cursor->in_exhaust) {
570572
if (!_mongoc_client_warm_up (cursor->client, &cursor->error)) {
571573
cursor->failed = true;
572574
RETURN (false);
@@ -577,7 +579,7 @@ _mongoc_cursor_get_more (mongoc_cursor_t *cursor)
577579
MONGOC_ERROR_CURSOR,
578580
MONGOC_ERROR_CURSOR_INVALID_CURSOR,
579581
"No valid cursor was provided.");
580-
goto failure;
582+
GOTO (failure);
581583
}
582584

583585
rpc.get_more.msg_len = 0;
@@ -601,7 +603,7 @@ _mongoc_cursor_get_more (mongoc_cursor_t *cursor)
601603
NULL, cursor->read_prefs, &cursor->error)) {
602604
cursor->done = true;
603605
cursor->failed = true;
604-
RETURN(false);
606+
RETURN (false);
605607
}
606608

607609
request_id = BSON_UINT32_FROM_LE(rpc.header.request_id);
@@ -721,9 +723,13 @@ mongoc_cursor_next (mongoc_cursor_t *cursor,
721723
{
722724
bool ret;
723725

726+
ENTRY;
727+
724728
BSON_ASSERT(cursor);
725729
BSON_ASSERT(bson);
726730

731+
TRACE ("cursor_id(%"PRId64")", cursor->rpc.reply.cursor_id);
732+
727733
if (cursor->iface.next) {
728734
ret = cursor->iface.next(cursor, bson);
729735
} else {
@@ -747,52 +753,72 @@ _mongoc_cursor_next (mongoc_cursor_t *cursor,
747753

748754
ENTRY;
749755

750-
BSON_ASSERT(cursor);
751-
752-
if (cursor->client->in_exhaust && ! cursor->in_exhaust) {
753-
bson_set_error(&cursor->error,
754-
MONGOC_ERROR_CLIENT,
755-
MONGOC_ERROR_CLIENT_IN_EXHAUST,
756-
"Another cursor derived from this client is in exhaust.");
757-
cursor->failed = true;
758-
RETURN(false);
759-
}
756+
BSON_ASSERT (cursor);
760757

761758
if (bson) {
762759
*bson = NULL;
763760
}
764761

762+
if (cursor->done || cursor->failed) {
763+
bson_set_error (&cursor->error,
764+
MONGOC_ERROR_CURSOR,
765+
MONGOC_ERROR_CURSOR_INVALID_CURSOR,
766+
"Cannot advance a completed or failed cursor.");
767+
RETURN (false);
768+
}
769+
770+
/*
771+
* We cannot proceed if another cursor is receiving results in exhaust mode.
772+
*/
773+
if (cursor->client->in_exhaust && !cursor->in_exhaust) {
774+
bson_set_error (&cursor->error,
775+
MONGOC_ERROR_CLIENT,
776+
MONGOC_ERROR_CLIENT_IN_EXHAUST,
777+
"Another cursor derived from this client is in exhaust.");
778+
cursor->failed = true;
779+
RETURN (false);
780+
}
781+
782+
/*
783+
* If we reached our limit, make sure we mark this as done and do not try to
784+
* make further progress.
785+
*/
765786
if (cursor->limit && cursor->count >= cursor->limit) {
766-
return false;
787+
cursor->done = true;
788+
RETURN (false);
767789
}
768790

769791
/*
770-
* Short circuit if we are finished already.
792+
* Try to read the next document from the reader if it exists, we might
793+
* get NULL back and EOF, in which case we need to submit a getmore.
771794
*/
772-
if (BSON_UNLIKELY(cursor->done)) {
773-
RETURN(false);
795+
if (cursor->reader) {
796+
eof = false;
797+
b = bson_reader_read (cursor->reader, &eof);
798+
cursor->end_of_event = eof;
799+
if (b) {
800+
GOTO (complete);
801+
}
774802
}
775803

776804
/*
777805
* Check to see if we need to send a GET_MORE for more results.
778806
*/
779807
if (!cursor->sent) {
780-
if (!_mongoc_cursor_query(cursor)) {
781-
RETURN(false);
808+
if (!_mongoc_cursor_query (cursor)) {
809+
RETURN (false);
782810
}
783-
} else if (BSON_UNLIKELY(cursor->end_of_event)) {
784-
if (!_mongoc_cursor_get_more(cursor)) {
785-
RETURN(false);
811+
} else if (BSON_UNLIKELY (cursor->end_of_event) && cursor->rpc.reply.cursor_id) {
812+
if (!_mongoc_cursor_get_more (cursor)) {
813+
RETURN (false);
786814
}
787815
}
788816

789-
/*
790-
* Read the next BSON document from the event.
791-
*/
792817
eof = false;
793-
b = bson_reader_read(cursor->reader, &eof);
818+
b = bson_reader_read (cursor->reader, &eof);
794819
cursor->end_of_event = eof;
795820

821+
complete:
796822
cursor->done = (cursor->end_of_event &&
797823
((cursor->in_exhaust && !cursor->rpc.reply.cursor_id) ||
798824
(!b && !(cursor->flags & MONGOC_QUERY_TAILABLE_CURSOR))));
@@ -803,18 +829,18 @@ _mongoc_cursor_next (mongoc_cursor_t *cursor,
803829
*/
804830
if (!b && !eof) {
805831
cursor->failed = true;
806-
bson_set_error(&cursor->error,
807-
MONGOC_ERROR_CURSOR,
808-
MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
809-
"The reply was corrupt.");
810-
RETURN(false);
832+
bson_set_error (&cursor->error,
833+
MONGOC_ERROR_CURSOR,
834+
MONGOC_ERROR_PROTOCOL_INVALID_REPLY,
835+
"The reply was corrupt.");
836+
RETURN (false);
811837
}
812838

813839
if (bson) {
814840
*bson = b;
815841
}
816842

817-
RETURN(!!b);
843+
RETURN (!!b);
818844
}
819845

820846

0 commit comments

Comments
 (0)