[CXX-1258] Cursor iterators lose lockstep at cursor end Created: 16/Mar/17  Updated: 28/Feb/18  Resolved: 27/Mar/17

Status: Closed
Project: C++ Driver
Component/s: Implementation
Affects Version/s: None
Fix Version/s: 3.2.0-rc0, 3.1.4

Type: Bug Priority: Major - P3
Reporter: David Golden Assignee: David Golden
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
depends on CDRIVER-2093 mongoc_cursor_is_alive and mongoc_cur... Closed
is depended on by CXX-1288 Add method to detect dead tailable cu... Closed

 Description   

When there are multiple iterators for a cursor, iterators should move in lockstep, meaning that incrementing any iterator is equivalent to incrementing all of them. This fails when an interator is incremented and there are no more documents. In that case, other iterators will not compare equal to cursor.end().

Example code:

#include <iostream>
#include <string>
 
#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/json.hpp>
#include <bsoncxx/stdx/string_view.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>
 
using bsoncxx::builder::basic::kvp;
 
int main() {
    auto inst = mongocxx::instance{};
    auto client = mongocxx::client{mongocxx::uri{}};
    auto coll = client["test"]["foo"];
    coll.drop();
 
    for (auto n : {1, 2, 3, 4}) {
        auto doc = bsoncxx::builder::basic::document{};
        doc.append(kvp("x", n));
        coll.insert_one(doc.extract());
    }
 
    auto cursor = coll.find({});
    auto iter = cursor.begin();
 
    for (auto&& doc : cursor) {
        std::cout << bsoncxx::to_json(doc) << std::endl;
    }
 
    auto cond = iter == cursor.end() ? std::string("==") : std::string("!=");
    std::cout << "iter " << cond << " cursor.end()" << std::endl;
 
    return EXIT_SUCCESS;
}

{ "_id" : { "$oid" : "58cab1205a4e4090514b7822" }, "x" : 1 }
{ "_id" : { "$oid" : "58cab1205a4e4090514b7823" }, "x" : 2 }
{ "_id" : { "$oid" : "58cab1205a4e4090514b7824" }, "x" : 3 }
{ "_id" : { "$oid" : "58cab1205a4e4090514b7825" }, "x" : 4 }
iter != cursor.end()

The current way that iterators are marked "at the end" is by setting their _cursor member to nullptr. This means that a cursor that doesn't yet know that it's at the end won't compare equal to the cursor.end() iterator with a nullptr _cursor.

Iterator equality comparison needs to be enhanced so that comparing a nullptr _cursor with a non-null _cursor has some additional way to see if _cursor has actually been exhausted.



 Comments   
Comment by Githook User [ 27/Mar/17 ]

Author:

{u'username': u'xdg', u'name': u'David Golden', u'email': u'xdg@xdg.me'}

Message: CXX-1258 Keep cursor iterators in lockstep at end

This commit fixes a bug where iterators might not always compare
equal to cursor.end() when the cursor was actually exhausted.

It adds extensive tests for cursor lockstep and invariants.

It also substantially revises cursor/iterator documentation for
exhaustion, equality comparison, and tailable cursor behavior.
Branch: master
https://github.com/mongodb/mongo-cxx-driver/commit/667a833f5ccc26d54aac8e20932e70ca16f1a3e9

Comment by David Golden [ 27/Mar/17 ]

We're going to finish this work as is and open CXX-1288 for the fix for tailable cursors that is blocking on libmongoc 1.7.0.

Comment by David Golden [ 22/Mar/17 ]

On hold, pending information from the C driver team on how/when they plan to address CDRIVER-2093.

Comment by David Golden [ 22/Mar/17 ]

Blocked waiting on investigation/fixes of libmongoc cursor bugs.

Generated at Wed Feb 07 22:01:58 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.