Skip to content

Conversation

@acmorrow
Copy link
Contributor

  • We can't assume that libmongoc has automatically called init/cleanup
    for us. It only does that on some platforms. That makes it mandatory
    to have an instance object. Many of our tests didn't do that, and it
    would be painful for users. Set things up so that an instance is
    implicitly created as needed, and provide ways to retrieve the
    instance. This required moving the tests for instance to its own
    process, among other nuisances.
  • The collection::create_index method was not cleaning up the keys that
    had been allocated by libbson. Add the needed bson_free call.
  • The collection::distinct method was not cleaning up the temorary
    database object that it constructs. Add the needed database_destroy
    call.
  • Fix some mocks so that they write to the bson_error_t out parameter
    when returning a non-successful code, as otherwise these lead to
    read-from-uninit errors when we promote the uninitialized bson_error_t
    to an exception.

@acmorrow
Copy link
Contributor Author

@hanumantmk @amidvidy @ajdavis I'd be interested in your thoughts on the changes around instance. I don't love them, but we do need a better story on how we initialize and terminate the driver. The other option would be to unroll these changes, and figure out how to get all of the catch tests to share an instance object.

@acmorrow
Copy link
Contributor Author

Ping?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible to error with a helpful message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good suggestion. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@acmorrow
Copy link
Contributor Author

One thing to note in this review is that it is still possible to fail to initialize the C driver correctly. For instance, if the first thing you constructed was a read_preference object, you might end up calling mongoc_read_prefs_new before an instance was constructed.

Another way to go with this change would be to unwind my auto-instance work in client and pool, and fix all of the tests and examples to manually create an instance (we could keep the automatic global instance though).

Thoughts?

@ajdavis
Copy link
Member

ajdavis commented Jan 21, 2016

To the extent I understand C++, the code looks fine to me.

But I dislike the philosophy of this approach: the driver should require users to explicitly call init and cleanup.

The C Driver should require you to call mongoc_init and mongoc_cleanup, and on non-GCC it does require you to call them. (There is a misfeature that uses GCC tricks to do call init and cleanup automatically, I plan to remove that in the C Driver 2.0.)

So, for the sake of correctness, clarity, simplicity, I propose requiring the user to init and cleanup the C++ driver explicitly.

@acmorrow
Copy link
Contributor Author

@ajdavis I think I agree. However, requiring them to drag around an object forever seems cruel. I think what I will do is to unwind the magic auto-initialization in client and pool, but retain the ability for 'instance' to manage a singleton. Then, I'll plumb calls to instance::current() through all the tests, ensuring that the global instance has been constructed. Does that sound reasonable?

@ajdavis
Copy link
Member

ajdavis commented Jan 21, 2016

Oh, I misunderstood, partly. I was arguing that the C++ driver should make the user do something manually that executes the C Driver's global initialization and cleanup routines, the same way the C Driver requires users to call mongoc_init and mongoc_cleanup themselves.

I don't have an opinion about the "instance" object, I'm not familiar with what it does.

@acmorrow
Copy link
Contributor Author

@ajdavis The instance object is exactly that. When constructed, it causes mongoc_init to be called. When destroyed, it causes mongoc_cleanup to be called.

@acmorrow
Copy link
Contributor Author

Updated, PTAL. No longer automatically creates an instance for you, so all the tests now call instance::current() to ensure that one exists. That is overkill, but safe. Also, made it so that instance now throws if you attempt to construct more than one.

@ajdavis
Copy link
Member

ajdavis commented Jan 22, 2016

LGTM.

In the docs, do you or will you recommend that C++ driver users make an
"instance" on the stack at the top of main()? If that's all a user must do
in C++ that's great.

Our examples show mongoc_init and mongoc_cleanup at the top and bottom of
main().

On Thu, Jan 21, 2016 at 3:39 PM, Andrew C. Morrow [email protected]
wrote:

Updated, PTAL. No longer automatically creates an instance for you, so all
the tests now call instance::current() to ensure that one exists. That is
overkill, but safe. Also, made it so that instance now throws if you
attempt to construct more than one.


Reply to this email directly or view it on GitHub
#441 (comment)
.

@acmorrow
Copy link
Contributor Author

@ajdavis Yes that is the idea. I doubt we have it documented anywhere yet though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alphabetize?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per discussion, we can't do with enums (or lots of other things to) because ABI. However, we haven't set an ABI yet, so I will put it in the right place.

@samantharitter
Copy link
Contributor

A few nits, also consider adding a test that we throw if you attempt to use the driver without creating an instance, otherwise LGTM

@samantharitter
Copy link
Contributor

Oh actually why don't the examples also need instance::current() ?

@samantharitter
Copy link
Contributor

LGTM after in-person discussion

@acmorrow
Copy link
Contributor Author

  • re the adding a test: we can't detect if you fail to set up, so I don't think we can test that. I could write a test that making an instance twice throws. Do you think that is worth it?
  • Re the examples, they already do it, by declaring an instance object as mongocxx::instance instance{}, so they don't need to call instance:current().

 - We can't assume that libmongoc has automatically called init/cleanup
   for us. It only does that on some platforms. That makes it mandatory
   to have an instance object. Many of our tests didn't do that.

 - The collection::create_index method was not cleaning up the keys that
   had been allocated by libbson. Add the needed bson_free call.

 - The collection::distinct method was not cleaning up the temorary
   database object that it constructs. Add the needed database_destroy
   call.

 - Fix some mocks so that they write to the bson_error_t out parameter
   when returning a non-successful code, as otherwise these lead to
   read-from-uninit errors when we promote the uninitialized
   bson_error_t to an exception.
@samantharitter
Copy link
Contributor

Eh, I'm fine without the test too

@acmorrow acmorrow merged commit 1a6f33d into mongodb:master Jan 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants