Successive get_iterator handler invocations should throw a LogicException. This avoids situations that might allow the user to iterate over the same cursor multiple times.
php_phongo_cursor_iterator_dtor() should not need to free the current element, which is stored on our cursor struct. If the cursor is only used by one iterator, zval_ptr_dtor() on the iterator's intern.data property (i.e. our Cursor zval) will implicitly call the free_object handler, which will invoke php_phongo_cursor_free() and clear the current element.
libmongoc already provides a mechanism to upgrade a cursor with a single command result document into a command cursor, which will seamlessly iterate through the first batch and documents returned by successive getmore ops.
This allows us to remove our own "first batch" handling and simplify the move_forward and rewind iteration handlers.
The current element is already freed at the top of this function. After that point, the element could only be intialized from first_batch_iter (after which we return immediately) or if mongoc_cursor_next() returns true (in which case we wouldn't be in this else clause).
This removes the invalidate_current handler. Due to SPL's implementation, our handler was being invoked between rewinding and checking if the current position was valid. Given that our validity check depends on inspecting a pointer to the current element (like MySQLi's result iterator), we cannot use invalidate_current.
The current element must still be freed during iteration, so we will instead call a php_phongo_cursor_free_current() function as needed. Additionally, we should track a reference to the Cursor object zval on the iterator itself, which will ensure it is not garbage-collected during iteration (demonstrated in the segfault backtrace in PHPC-215).
Lastly, this commit renames the Cursor object and iterator structs and related functions to be more consistent with implementions in PHP core.
There is a shutdown race condition in the mongoc counters segment
allocation where zend mm will free the counters during RSHUTDOWN.
This happens as there is no "persistent alloc" callback from the bson
allocators that we can pemalloc() for.
Instead, we'll let mongoc_init use its own alloctors -- but we have to
remember to reset the alloc callbacks before mongoc_cleanup()